1. 程式人生 > >MINA框架原始碼分析(二)

MINA框架原始碼分析(二)

 上一篇我們通過例項學習了MINA框架的用法,發現用起來還是挺方便的,就那麼幾步就可以了,本著學東西必知其原理的觀念,決定看看MINA的原始碼實現,好了,我們開始吧!

        MINA原始碼對於客戶端和服務端來說基本上差別不是很大的,所以我計劃主要還是分析服務端的原始碼,在正式分析之前,我們需要對MINA有一個整體的瞭解;

        MINA中涉及到了這麼幾個物件:

        IoService:用於提供連線,他是IoAcceptor和IoConnector的父介面;

        IoBuffer:訊息快取區;

        IoSession:在每一次連線建立成功之後都會建立一個IoSession物件出來,並且在建立該物件的時候建立一個IoFilter物件出來,通過IoSession的session id來為當前IoSession設定處理他的IoProcessor;

        IoProcessor:用於檢查是否有資料在通道上面進行讀寫,在我們建立Acceptor或者Connector的時候,預設會建立一個執行緒池,裡面儲存的就是IoProcessor執行緒,該執行緒裡面是擁有自己的Selector的,這個是MINA為我們做的一點優化,我們通常使用NIO的話是隻有一個Selector的,而MINA中的

        IoFilter:用於定義攔截器,這些攔截器可以包括日誌輸出、資料編解碼等等,只要用於二進位制資料和物件之間的轉換;

        IoHandler:處於IoFilter的尾部,用於真正的業務邏輯處理,所以我們在使用MINA的時候是必須要提供IoHandler物件的,因為是靠他來進行真正業務處理的;

        接下來我們看看上篇部落格中我們用到的MINA中涉及到的這幾個物件的類結構圖:

        NioSocketAcceptor類結構圖:

                   

        NioSocketConnector類結構圖:

                   

        NioSocketSession類結構圖:

                                                            

        NioProcessor類結構圖:

                                             


        好了,開始我們真正的原始碼分析了(服務端);

        首先我們通過NioSocketAcceptor acceptor = new NioSocketAcceptor();建立了一個NioSocketAcceptor物件出來,那我們就得看看NioSocketAcceptor的建構函式裡面做了些什麼事了;

       NioSocketAcceptor$NioSocketAcceptor()

  1. public NioSocketAcceptor() {  
  2.         super(new DefaultSocketSessionConfig(), NioProcessor.class);  
  3.         ((DefaultSocketSessionConfig) getSessionConfig()).init(this);  
  4.     }  
        可以看到首先呼叫了父類的建構函式,也就是AbstractPollingIoAcceptor的建構函式,並且傳入了NioProcessor的Class物件,這裡我們可以想象一下後面肯定會用這個NioProcessor的Class物件進行一些與反射有關的操作;

        AbstractPollingIoAcceptor$AbstractPollingIoAcceptor()

  1. protected AbstractPollingIoAcceptor(IoSessionConfig sessionConfig, Class<? extends IoProcessor<S>> processorClass) {  
  2.         this(sessionConfig, nullnew SimpleIoProcessorPool<S>(processorClass), truenull);  
  3.     }  
        可以看到實際上呼叫的是5個引數的建構函式,在看這個建構函式之前,我們看到第三個引數利用我們從NioSocketAcceptor建構函式中傳進來的NioProcessor物件,建立了一個SimpleIoProcessorPool物件,我們來看看SimpleIoProcessorPool的建構函式;
        SimpleIoProcessorPool$SimpleIoProcessorPool()   

  1. public SimpleIoProcessorPool(Class<? extends IoProcessor<S>> processorType) {  
  2.      this(processorType, null, DEFAULT_SIZE, null);  
  3.  }  
        發現他接著呼叫的是SimpleIoProcessorPool四個引數的建構函式,並且添加了一個DEFAULT_SIZE引數,這個值的大小等於我們CPU的核數+1,這也是我們在建立NioSocketAcceptor的時候預設建立的NioProcessor的執行緒個數,來看看SimpleIoProcessorPool四個引數的建構函式:
  1. public SimpleIoProcessorPool(Class<? extends IoProcessor<S>> processorType, Executor executor, int size,   
  2.             SelectorProvider selectorProvider) {  
  3.         if (processorType == null) {  
  4.             thrownew IllegalArgumentException("processorType");  
  5.         }  
  6.         if (size <= 0) {  
  7.             thrownew IllegalArgumentException("size: " + size + " (expected: positive integer)");  
  8.         }  
  9.         // Create the executor if none is provided
  10.         createdExecutor = (executor == null);  
  11.         if (createdExecutor) {  
  12.             this.executor = Executors.newCachedThreadPool();  
  13.             // Set a default reject handler
  14.             ((ThreadPoolExecutor) this.executor).setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());  
  15.         } else {  
  16.             this.executor = executor;  
  17.         }  
  18.         pool = new IoProcessor[size];  
  19.         boolean success = false;  
  20.         Constructor<? extends IoProcessor<S>> processorConstructor = null;  
  21.         boolean usesExecutorArg = true;  
  22.         try {  
  23.             // We create at least one processor
  24.             try {  
  25.                 try {  
  26.                     processorConstructor = processorType.getConstructor(ExecutorService.class);  
  27.                     pool[0] = processorConstructor.newInstance(this.executor);  
  28.                 } catch (NoSuchMethodException e1) {  
  29.                     // To the next step...
  30.                     try {  
  31.                         if(selectorProvider==null) {  
  32.                             processorConstructor = processorType.getConstructor(Executor.class);  
  33.                             pool[0] = processorConstructor.newInstance(this.executor);  
  34.                         } else {  
  35.                             processorConstructor = processorType.getConstructor(Executor.class, SelectorProvider.class);  
  36.                             pool[0] = processorConstructor.newInstance(this.executor,selectorProvider);  
  37.                         }  
  38.                     } catch (NoSuchMethodException e2) {  
  39.                         // To the next step...
  40.                         try {  
  41.                             processorConstructor = processorType.getConstructor();  
  42.                             usesExecutorArg = false;  
  43.                             pool[0] = processorConstructor.newInstance();  
  44.                         } catch (NoSuchMethodException e3) {  
  45.                             // To the next step...
  46.                         }  
  47.                     }  
  48.                 }  
  49.             } catch (RuntimeException re) {  
  50.                 LOGGER.error("Cannot create an IoProcessor :{}", re.getMessage());  
  51.                 throw re;  
  52.             } catch (Exception e) {  
  53.                 String msg = "Failed to create a new instance of " + processorType.getName() + ":" + e.getMessage();  
  54.                 LOGGER.error(msg, e);  
  55.                 thrownew RuntimeIoException(msg, e);  
  56.             }  
  57.             if (processorConstructor == null) {  
  58.                 // Raise an exception if no proper constructor is found.
  59.                 String msg = String.valueOf(processorType) + " must have a public constructor with one "
  60.                         + ExecutorService.class.getSimpleName() + " parameter, a public constructor with one "
  61.                         + Executor.class.getSimpleName() + " parameter or a public default constructor.";  
  62.                 LOGGER.error(msg);  
  63.                 thrownew IllegalArgumentException(msg);  
  64.             }  
  65.             // Constructor found now use it for all subsequent instantiations
  66.             for (int i = 1; i < pool.length; i++) {  
  67.                 try {  
  68.                     if (usesExecutorArg) {  
  69.                         if(selectorProvider==null) {  
  70.                             pool[i] = processorConstructor.newInstance(this.executor);  
  71.                         } else {  
  72.                             pool[i] = processorConstructor.newInstance(this.executor, selectorProvider);  
  73.                         }  
  74.                     } else {