小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

深入解析Apache Mina源碼(2)——Mina的事件模型

 集微筆記 2014-02-24
一、觀察者模式的本來面目

工作時間長了,會發(fā)現(xiàn)代碼中的很多東西都是相通相似的,就說JAVA的事件機制其實就是觀察者模式的實現(xiàn),學(xué)會了觀察者模式,事件機制自己無師自通,先以我的角度看看什么是觀察者模式。

觀察者模式,顧名思義,應(yīng)該有觀察者(抽象觀察者“Observer”角色)和被觀察者(抽象主題“Subject”角色),被觀察者一旦有變化就通知觀察者更新自己。

形象圖:



下面是觀察者模式的類圖:




從我的角度簡單點理解,我們知道面向?qū)ο缶幊滩贿^是對象之間的相互調(diào)用,那么被觀察者應(yīng)該有個列表(List)來把所有觀察者引用起來,當有事件要通知觀察者時,我們從List中把所有觀察者類取出來挨個調(diào)用觀察者的方法(如update())。這個過程中只有充分利用了面向?qū)ο缶幊痰亩鄳B(tài),繼承等特性才能實現(xiàn)。

下面是代碼實現(xiàn):

被觀察者(抽象主題類):

Java代碼 復(fù)制代碼 收藏代碼
  1. package com.lifanghu.observer;   
  2.   
  3. import java.util.ArrayList;   
  4. import java.util.List;   
  5.   
  6. /**  
  7.  * @author lifh  
  8.  * @mail wslfh2005@163.com  
  9.  * @since 2012-6-14 下午06:18:26  
  10.  * @name com.lifanghu.observer.Subject.java  
  11.  * @version 1.0  
  12.  */  
  13. public abstract class Subject {   
  14.   
  15.     private List observers = new ArrayList();   
  16.   
  17.     /**  
  18.      * 增加一個觀察者  
  19.      * @param observer  
  20.      * @author lifh  
  21.      */  
  22.     public void addObserver(Observer observer) {   
  23.         observers.add(observer);   
  24.     }   
  25.     /**  
  26.      * 刪除一個觀察者  
  27.      * @param observer  
  28.      * @author lifh  
  29.      */  
  30.     public void removeObserver(Observer observer) {   
  31.         observers.remove(observer);   
  32.     }   
  33.     /**  
  34.      * 通知所有觀察者  
  35.      * @author lifh  
  36.      */  
  37.     public void notifyObservers() {   
  38.         for (Observer observer : observers) {   
  39.             observer.update(this);   
  40.         }   
  41.     }   
  42. }   

  實際被觀察者(真實主題角色):

Java代碼 復(fù)制代碼 收藏代碼
  1. package com.lifanghu.observer;   
  2.   
  3. /**  
  4.  * 實際被觀察者  
  5.  * @author lifh  
  6.  * @mail wslfh2005@163.com  
  7.  * @since 2012-6-14 下午10:48:02  
  8.  * @name com.lifanghu.observer.XiaoMing.java  
  9.  * @version 1.0  
  10.  */  
  11. public class XiaoMing extends Subject {   
  12.   
  13.     private String state;   
  14.   
  15.     //實際要通進行通知的方法   
  16.     public void change() {   
  17.         this.notifyObservers();   
  18.     }   
  19.     public String getState() {   
  20.         return state;   
  21.     }   
  22.     public void setState(String state) {   
  23.         this.state = state;   
  24.     }   
  25. }  
 抽象觀察者:
Java代碼 復(fù)制代碼 收藏代碼
  1. package com.lifanghu.observer;   
  2.   
  3. /**  
  4.  * 實際觀察者  
  5.  * @author lifh  
  6.  * @mail wslfh2005@163.com  
  7.  * @since 2012-6-14 下午10:54:07  
  8.  * @name com.lifanghu.observer.XiaoWang.java  
  9.  * @version 1.0  
  10.  */  
  11. public class XiaoWang implements Observer {   
  12.   
  13.     public void update(Subject subject) {   
  14.         XiaoMing xm = (XiaoMing) subject;   
  15.         System.out.println("小王得到通知:" + xm.getState() + ";小王說:活該!");   
  16.     }   
  17. }   

  具體觀察者1:

Java代碼 復(fù)制代碼 收藏代碼
  1. package com.lifanghu.observer;   
  2.   
  3. /**  
  4.  * 實際觀察者  
  5.  * @author lifh  
  6.  * @mail wslfh2005@163.com  
  7.  * @since 2012-6-14 下午10:54:07  
  8.  * @name com.lifanghu.observer.XiaoWang.java  
  9.  * @version 1.0  
  10.  */  
  11. public class XiaoWang implements Observer {   
  12.   
  13.     public void update(Subject subject) {   
  14.         XiaoMing xm = (XiaoMing) subject;   
  15.         System.out.println("小王得到通知:" + xm.getState() + ";小王說:活該!");   
  16.     }   
  17. }  
 具體觀察者2:
Java代碼 復(fù)制代碼 收藏代碼
  1. package com.lifanghu.observer;   
  2.   
  3. /**  
  4.  * 實際觀察者  
  5.  * @author lifh  
  6.  * @mail wslfh2005@163.com  
  7.  * @since 2012-6-14 下午10:56:17  
  8.  * @name com.lifanghu.observer.ZhangShan.java  
  9.  * @version 1.0  
  10.  */  
  11. public class ZhangShan implements Observer {   
  12.   
  13.     public void update(Subject subject) {   
  14.         XiaoMing xm = (XiaoMing) subject;   
  15.         System.out.println("張三得到通知:" + xm.getState() + ";張三說:快吃藥吧!");   
  16.     }   
  17. }  
 客戶端調(diào)用邏輯:
Java代碼 復(fù)制代碼 收藏代碼
  1. package com.lifanghu.observer;   
  2.   
  3. /**  
  4.  * 實際觀察者  
  5.  * @author lifh  
  6.  * @mail wslfh2005@163.com  
  7.  * @since 2012-6-14 下午10:56:17  
  8.  * @name com.lifanghu.observer.ZhangShan.java  
  9.  * @version 1.0  
  10.  */  
  11. public class ZhangShan implements Observer {   
  12.   
  13.     public void update(Subject subject) {   
  14.         XiaoMing xm = (XiaoMing) subject;   
  15.         System.out.println("張三得到通知:" + xm.getState() + ";張三說:快吃藥吧!");   
  16.     }   
  17. }  
 輸出結(jié)果:
 寫道
張三得到通知:小明病了;張三說:快吃藥吧!
小王得到通知:小明病了;小王說:活該!
        說明:對于觀察者模式JDK是有相應(yīng)的實現(xiàn)支持的,內(nèi)置觀察者模式主要有2個類,一個是類Observable,一個是接口類Observer ,大家可以上網(wǎng)去查,或者直接看它的源碼,這里就不多說了。

 

二、從觀察者模式到事件機制

關(guān)于事件機制上面也談了,它其實就是觀察者模式的實現(xiàn),關(guān)于兩者的聯(lián)系也可以看iteye上的另一討論http://www./topic/182643,里面說的已經(jīng)很清楚了。

關(guān)于事件模型我想說的是里面的三個元素:事件源,事件本身,監(jiān)聽者,對應(yīng)觀察者模式的三個元素分別是:被觀察者,觀察者方法要傳入的參數(shù),觀察者。

關(guān)于事件機制JDK也有相應(yīng)的實現(xiàn)java.util.EventListenerjava.util.EventObject 。

三、Mina中的事件以及監(jiān)聽器的實現(xiàn)

Mina 中有主要有三種事件:

1org.apache.mina.core.service包下面對IoService接口實現(xiàn)和IoSession接口實現(xiàn)的監(jiān)聽,它不是一個純的事件模型,沒有事件本身(EventObject)的存在。

2、org.apache.mina.core.session包下在線程池環(huán)境下對于事件的觸發(fā)從而進入過濾器鏈進行的處理,它不是一個純事件的模型,少了監(jiān)聽器(EventListener)的實現(xiàn)。

3org.apache.mina.core.future包下對于異步IO操作(IoFuture)進行監(jiān)聽。它也不是一個純的事件模型,也是少了事件本身(EventObject)的存在。

下面分別介紹下這三種事件細節(jié)。

1service包下面主要有兩個類是用于監(jiān)聽模式的,監(jiān)聽者IoServiceListener和它的幫助類IoServiceListenerSupport,IoServiceListener接口繼承了EventListener,標明自己是個監(jiān)聽者接口,主要監(jiān)聽servicesession的創(chuàng)建,空閑,銷毀事件的。IoServiceListenerSupport作為它的幫助類,實際上充當了事件源的角色,它存儲了IoServiceListener的成員列表。

Java代碼 復(fù)制代碼 收藏代碼
  1. /** A list of {@link IoServiceListener}s. */  
  2. private final List listeners = new CopyOnWriteArrayList();  

 里面有增加和刪除監(jiān)聽者的方法:

Java代碼 復(fù)制代碼 收藏代碼
  1. /**  
  2.  * Adds a new listener.  
  3.  *   
  4.  * @param listener The added listener  
  5.  */  
  6. public void add(IoServiceListener listener) {   
  7.     if (listener != null) {   
  8.         listeners.add(listener);   
  9.     }   
  10. }   
  11.   
  12. /**  
  13.  * Removes an existing listener.  
  14.  *   
  15.  * @param listener The listener to remove  
  16.  */  
  17. public void remove(IoServiceListener listener) {   
  18.     if (listener != null) {   
  19.         listeners.remove(listener);   
  20.     }   
  21. }  

通知監(jiān)聽者的方法:

Java代碼 復(fù)制代碼 收藏代碼
  1. /**  
  2.  * Calls {@link IoServiceListener#serviceActivated(IoService)}  
  3.  * for all registered listeners.  
  4.  * 通知方法  
  5.  */  
  6. public void fireServiceActivated() {   
  7.     if (!activated.compareAndSet(falsetrue)) {   
  8.         // The instance is already active   
  9.         return;   
  10.     }   
  11.   
  12.     activationTime = System.currentTimeMillis();   
  13.   
  14.     // Activate all the listeners now   
  15.     for (IoServiceListener listener : listeners) {//循環(huán)提取出listeners執(zhí)行本身的方法   
  16.         try {   
  17.             listener.serviceActivated(service);   
  18.         } catch (Throwable e) {   
  19.             ExceptionMonitor.getInstance().exceptionCaught(e);   
  20.         }   
  21.     }   
  22. }  

再來看接口IoService,有對監(jiān)聽器的操作:

Java代碼 復(fù)制代碼 收藏代碼
  1. /**  
  2.  * Adds an {@link IoServiceListener} that listens any events related with  
  3.  * this service.  
  4.  */  
  5. void addListener(IoServiceListener listener);   
  6.   
  7. /**  
  8.  * Removed an existing {@link IoServiceListener} that listens any events  
  9.  * related with this service.  
  10.  */  
  11. void removeListener(IoServiceListener listener);  

 它的實現(xiàn)AbstractIoService里面可以看到,實際是調(diào)用的IoServiceListenerSupport的方法執(zhí)行的有關(guān)操作:

Java代碼 復(fù)制代碼 收藏代碼
  1. /**  
  2.  * {@inheritDoc}  
  3.  */  
  4. public final void addListener(IoServiceListener listener) {   
  5.     listeners.add(listener);   
  6. }   
  7.   
  8. /**  
  9.  * {@inheritDoc}  
  10.  */  
  11. public final void removeListener(IoServiceListener listener) {   
  12.     listeners.remove(listener);   
  13. }  

 看下AbstractIoAcceptor類的調(diào)用方法:

Java代碼 復(fù)制代碼 收藏代碼
  1. if (activate) {   
  2.     //觸發(fā)監(jiān)聽器的服務(wù)創(chuàng)建事件   
  3.     getListeners().fireServiceActivated();   
  4. }  

 2、session包下的事件模型主要還是基于多線程模型來實現(xiàn)的,可以看到IoEvent實現(xiàn)了Runnable接口,它作為任務(wù)放入到線程池中去執(zhí)行,看它的run方法:

Java代碼 復(fù)制代碼 收藏代碼
  1. // 此類實現(xiàn)了 Runnable 它的存在主要為了線程池過濾器ExecutorFilter來使用的。   
  2. // 這樣如果加入了ExecutorFilter后,后面所有的數(shù)據(jù)處理都是多線程方式進行的。   
  3. // 一般放在handler前面,也就是所有過濾器的后面,因為handler主要做業(yè)務(wù)處理,可能會有數(shù)據(jù)庫的操作,比較耗時,適合多線程。   
  4. public void run() {   
  5.     //激活各種事件   
  6.     fire();   
  7. }  

 IO事件類型:

Java代碼 復(fù)制代碼 收藏代碼
  1. package org.apache.mina.core.session;   
  2.   
  3. /**  
  4.  * An {@link Enum} that represents the type of I/O events and requests.  
  5.  * Most users won't need to use this class.  It is usually used by internal  
  6.  * components to store I/O events.  
  7.  *  
  8.  * @author Apache MINA Project  
  9.  */  
  10. public enum IoEventType {   
  11.     SESSION_CREATED,//session創(chuàng)建   
  12.     SESSION_OPENED,//session打開   
  13.     SESSION_CLOSED,//session關(guān)閉   
  14.     MESSAGE_RECEIVED,//消息接收   
  15.     MESSAGE_SENT,//消息發(fā)送   
  16.     SESSION_IDLE,//session空閑   
  17.     EXCEPTION_CAUGHT,//發(fā)生異常   
  18.     WRITE,//寫事件   
  19.     CLOSE,//關(guān)閉session事件   
  20. }  

 它有一個實現(xiàn)類IoFilterEvent,我們知道如果我們想要利用mina的多線程處理,需要如下加一個過濾器:

Java代碼 復(fù)制代碼 收藏代碼
  1. connector.getFilterChain().addLast("executor"new ExecutorFilter());  

 在這個時候我們的IoEvent就派上了用場,ExecutorFilter是一個實現(xiàn)了線程池(線程池在后面的文章中會介紹)的過濾器,看下ExecutorFilter的調(diào)用:

Java代碼 復(fù)制代碼 收藏代碼
  1. @Override  
  2. public final void sessionOpened(NextFilter nextFilter, IoSession session) {   
  3.     if (eventTypes.contains(IoEventType.SESSION_OPENED)) {   
  4.         IoFilterEvent event = new IoFilterEvent(nextFilter, IoEventType.SESSION_OPENED,   
  5.             session, null);    
  6.         //觸發(fā)事件   
  7.         fireEvent(event);   
  8.     } else {   
  9.         nextFilter.sessionOpened(session);   
  10.     }   
  11. }   
  12. /**  
  13.  * Fires the specified event through the underlying executor.  
  14.  *   
  15.  * @param event The filtered event  
  16.  */  
  17. protected void fireEvent(IoFilterEvent event) {   
  18.     //將事件提交給線程池執(zhí)行   
  19.     executor.execute(event);   
  20. }  

 可以看到這個session下的事件模型沒有監(jiān)聽器,所以基本就沒有事件模式的概念了,但是還是有一些事件模型的一些影子,所以可以認為它是一個偽事件模型。

3、future包下面的事件模型,是比較常規(guī)的事件模型,這是一個異步調(diào)用后的事件模型,當設(shè)定的異步操作完成后會調(diào)用監(jiān)聽器的operationComplete方法,事件源為IoFuture等,監(jiān)聽器是IoFutureListener,它只有一個方法:

Java代碼 復(fù)制代碼 收藏代碼
  1. /**  
  2.  * Invoked when the operation associated with the {@link IoFuture}  
  3.  * has been completed even if you add the listener after the completion.  
  4.  * 只有一個處理完成的回調(diào)方法,當線程池將我們的任務(wù)處理完成后會調(diào)用此方法。  
  5.  * @param future  The source {@link IoFuture} which called this  
  6.  *                callback.  
  7.  */  
  8. void operationComplete(F future);  

 看下事件源的代碼:

Java代碼 復(fù)制代碼 收藏代碼
  1. package org.apache.mina.core.future;   
  2.   
  3. import java.util.concurrent.TimeUnit;   
  4.   
  5. import org.apache.mina.core.session.IoSession;   
  6.   
  7. /**  
  8.  * Represents the completion of an asynchronous I/O operation on an   
  9.  * {@link IoSession}.  
  10.  * Can be listened for completion using a {@link IoFutureListener}.  
  11.  * 因為有了線程池模型才會有異步的概念。  
  12.  * 我們將各種IO操作(連接,關(guān)閉,讀,寫)以任務(wù)的方式放入隊列中并返回IoFuture供線程池去處理。  
  13.  * 處理過程和處理完成的操作會改變IoFuture的狀態(tài)。  
  14.  * @author Apache MINA Project  
  15.  */  
  16. public interface IoFuture {   
  17.     /**  
  18.      * Returns the {@link IoSession} which is associated with this future.  
  19.      */  
  20.     IoSession getSession();   
  21.   
  22.     /**  
  23.      * Wait for the asynchronous operation to complete.  
  24.      * The attached listeners will be notified when the operation is   
  25.      * completed.  
  26.      */  
  27.     IoFuture await() throws InterruptedException;   
  28.   
  29.     /**  
  30.      * Wait for the asynchronous operation to complete with the specified timeout.  
  31.      * 等待操作在指定時間內(nèi)完成  
  32.      * @return true if the operation is completed.  
  33.      */  
  34.     boolean await(long timeout, TimeUnit unit) throws InterruptedException;   
  35.   
  36.     /**  
  37.      * Wait for the asynchronous operation to complete with the specified timeout.  
  38.      *  
  39.      * @return true if the operation is completed.  
  40.      */  
  41.     boolean await(long timeoutMillis) throws InterruptedException;   
  42.   
  43.     /**  
  44.      * Wait for the asynchronous operation to complete uninterruptibly.  
  45.      * The attached listeners will be notified when the operation is   
  46.      * completed.  
  47.      * 等待異步操作完成,完成后會觸發(fā)注冊的監(jiān)聽器。  
  48.      * @return the current IoFuture  
  49.      */  
  50.     IoFuture awaitUninterruptibly();   
  51.   
  52.     /**  
  53.      * Wait for the asynchronous operation to complete with the specified timeout  
  54.      * uninterruptibly.  
  55.      *  
  56.      * @return true if the operation is completed.  
  57.      */  
  58.     boolean awaitUninterruptibly(long timeout, TimeUnit unit);   
  59.   
  60.     /**  
  61.      * Wait for the asynchronous operation to complete with the specified timeout  
  62.      * uninterruptibly.  
  63.      *  
  64.      * @return true if the operation is finished.  
  65.      */  
  66.     boolean awaitUninterruptibly(long timeoutMillis);   
  67.   
  68.     /**  
  69.      * @deprecated Replaced with {@link #awaitUninterruptibly()}.  
  70.      */  
  71.     @Deprecated  
  72.     void join();   
  73.   
  74.     /**  
  75.      * @deprecated Replaced with {@link #awaitUninterruptibly(long)}.  
  76.      */  
  77.     @Deprecated  
  78.     boolean join(long timeoutMillis);   
  79.   
  80.     /**  
  81.      * Returns if the asynchronous operation is completed.  
  82.      */  
  83.     boolean isDone();   
  84.   
  85.     /**  
  86.      * Adds an event listener which is notified when  
  87.      * this future is completed. If the listener is added  
  88.      * after the completion, the listener is directly notified.  
  89.      * 增加異步完成后的監(jiān)聽者  
  90.      */  
  91.     IoFuture addListener(IoFutureListener listener);   
  92.   
  93.     /**  
  94.      * Removes an existing event listener so it won't be notified when  
  95.      * the future is completed.  
  96.      * 刪除異步完成后的監(jiān)聽者  
  97.      */  
  98.     IoFuture removeListener(IoFutureListener listener);   
  99. }  

 看下調(diào)用監(jiān)聽者的方法類DefaultIoFuture的代碼:

Java代碼 復(fù)制代碼 收藏代碼
  1. /**  
  2.  * Sets the result of the asynchronous operation, and mark it as finished.  
  3.  */  
  4. public void setValue(Object newValue) {   
  5.     synchronized (lock) {   
  6.         // Allow only once.   
  7.         if (ready) {   
  8.             return;   
  9.         }   
  10.   
  11.         result = newValue;   
  12.         ready = true;   
  13.         if (waiters > 0) {   
  14.             lock.notifyAll();   
  15.         }   
  16.     }   
  17.   
  18.     //調(diào)用監(jiān)聽者的方法   
  19.     notifyListeners();   
  20. }  

 在此我們可以學(xué)到JAVA的異步只有在多線程操作下才有可能實現(xiàn)。

四、推薦文章

參考文章:

1. 觀察者模式

http://ttitfly./blog/152512

2. JAVA與模式》之觀察者模式

http://www.cnblogs.com/java-my-life/archive/2012/05/16/2502279.html

3. Java事件機制理解及應(yīng)用

http://blog.csdn.net/JianZhiZG/article/details/1427073

4. java 事件機制

http://www./chenweicai/archive/2007/04/13/110350.html

五、總結(jié)

事件模型作為mina中一個重要的設(shè)計模式很好的體現(xiàn)了JAVA高內(nèi)聚,低耦合的設(shè)計思想,也讓用戶的調(diào)用代碼簡潔易用,本文章本著拋磚引玉的態(tài)度希望大家能指出缺點,共同討論。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多