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()
- public NioSocketAcceptor() {
- super(new DefaultSocketSessionConfig(), NioProcessor.class);
- ((DefaultSocketSessionConfig) getSessionConfig()).init(this);
- }
AbstractPollingIoAcceptor$AbstractPollingIoAcceptor()
- protected AbstractPollingIoAcceptor(IoSessionConfig sessionConfig, Class<? extends IoProcessor<S>> processorClass) {
- this(sessionConfig, null, new SimpleIoProcessorPool<S>(processorClass), true, null);
- }
SimpleIoProcessorPool$SimpleIoProcessorPool()
- public SimpleIoProcessorPool(Class<? extends IoProcessor<S>> processorType) {
- this(processorType, null, DEFAULT_SIZE, null);
- }
- public SimpleIoProcessorPool(Class<? extends IoProcessor<S>> processorType, Executor executor, int size,
- SelectorProvider selectorProvider) {
- if (processorType == null) {
- thrownew IllegalArgumentException("processorType");
- }
- if (size <= 0) {
- thrownew IllegalArgumentException("size: " + size + " (expected: positive integer)");
- }
- // Create the executor if none is provided
- createdExecutor = (executor == null);
- if (createdExecutor) {
- this.executor = Executors.newCachedThreadPool();
- // Set a default reject handler
- ((ThreadPoolExecutor) this.executor).setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
- } else {
- this.executor = executor;
- }
- pool = new IoProcessor[size];
- boolean success = false;
- Constructor<? extends IoProcessor<S>> processorConstructor = null;
- boolean usesExecutorArg = true;
- try {
- // We create at least one processor
- try {
- try {
- processorConstructor = processorType.getConstructor(ExecutorService.class);
- pool[0] = processorConstructor.newInstance(this.executor);
- } catch (NoSuchMethodException e1) {
- // To the next step...
- try {
- if(selectorProvider==null) {
- processorConstructor = processorType.getConstructor(Executor.class);
- pool[0] = processorConstructor.newInstance(this.executor);
- } else {
- processorConstructor = processorType.getConstructor(Executor.class, SelectorProvider.class);
- pool[0] = processorConstructor.newInstance(this.executor,selectorProvider);
- }
- } catch (NoSuchMethodException e2) {
- // To the next step...
- try {
- processorConstructor = processorType.getConstructor();
- usesExecutorArg = false;
- pool[0] = processorConstructor.newInstance();
- } catch (NoSuchMethodException e3) {
- // To the next step...
- }
- }
- }
- } catch (RuntimeException re) {
- LOGGER.error("Cannot create an IoProcessor :{}", re.getMessage());
- throw re;
- } catch (Exception e) {
- String msg = "Failed to create a new instance of " + processorType.getName() + ":" + e.getMessage();
- LOGGER.error(msg, e);
- thrownew RuntimeIoException(msg, e);
- }
- if (processorConstructor == null) {
- // Raise an exception if no proper constructor is found.
- String msg = String.valueOf(processorType) + " must have a public constructor with one "
- + ExecutorService.class.getSimpleName() + " parameter, a public constructor with one "
- + Executor.class.getSimpleName() + " parameter or a public default constructor.";
- LOGGER.error(msg);
- thrownew IllegalArgumentException(msg);
- }
- // Constructor found now use it for all subsequent instantiations
- for (int i = 1; i < pool.length; i++) {
- try {
- if (usesExecutorArg) {
- if(selectorProvider==null) {
- pool[i] = processorConstructor.newInstance(this.executor);
- } else {
- pool[i] = processorConstructor.newInstance(this.executor, selectorProvider);
- }
- } else {