1. 预览
依然遵循之前的原则,只看core(其实还包括了transport,虽然它不在core中,但socket相关的类在此包中),了解mina的内部机制,忽略细节,这里就直接从服务器的入口第一步开始,即连接管理的IOService。直接来看下对应的包:org.apache.mina.core.service。 by the way 我的mina源码版本是:2.0.7
通过包结构就可以说一下这部分的职能和相关的代码,先有个整个的印象。
可以总结成五部分:service责任(IoService)、Processor线程处理(IoProcessor)、handler处理器(IoHandler)、服务器端接收器(IoAcceptor)和客户端连接器(IoConnector),括号中是对应的处理接口,我们首先只讨论服务器架构图入口部分,即1、4、5。另外handler部分属于流程的末端,IoProcessor和IoSession密切相连,负责完成IoSession中一些实际的IO操作,不太适合在这部分介绍。
2. IOService
第一部分先说一下顶层的接口IOService,官方的介绍上给出了IOService的职能和abstract封装了一层的抽象类
对应着这几个功能看一下IoService的所有方法就比较清楚各个方法的作用了。因为是接口,看了这个接口大概就明白是做什么的了。
AbstractIoService的注释提到An instance of IoService contains an Executor which will handle the incoming events。而上面提到的不止这个功能,照着上面的功能去看相应的方法是个比较好的办法,就可以了解每部分怎么实现的,一眼看过去有些add,set,contain之类的方法都可以忽略了,这里最后的manages不要被字面误解,搜一下源码里的管理,其实只是maintain。那么就剩下了两个方法值得我们关注,一个就是注释提到的executor,另一个就是涉及到默认实现的dispose。
Creates Executor, if not provided(在构造方法中实现,觉着有些地方同样需要提一下跟整体的设计相关的,就增大的信息量,把构造方法都贴出来了):
- protected AbstractIoService(IoSessionConfig sessionConfig, Executor executor) {
- if (sessionConfig == null) {
- throw new IllegalArgumentException("sessionConfig");
- }
- if (getTransportMetadata() == null) {
- throw new IllegalArgumentException("TransportMetadata");
- }
- if (!getTransportMetadata().getSessionConfigType().isAssignableFrom(sessionConfig.getClass())) {
- throw new IllegalArgumentException("sessionConfig type: " + sessionConfig.getClass() + " (expected: "
- + getTransportMetadata().getSessionConfigType() + ")");
- }
- // Create the listeners, and add a first listener : a activation listener
- // for this service, which will give information on the service state.
- listeners = new IoServiceListenerSupport(this);
- listeners.add(serviceActivationListener);
- // Stores the given session configuration
- this.sessionConfig = sessionConfig;
- // Make JVM load the exception monitor before some transports
- // change the thread context class loader.
- ExceptionMonitor.getInstance();
- if (executor == null) {
- this.executor = Executors.newCachedThreadPool();
- createdExecutor = true;
- } else {
- this.executor = executor;
- createdExecutor = false;
- }
- threadName = getClass().getSimpleName() + '-' + id.incrementAndGet();
- }
protected AbstractIoService(IoSessionConfig sessionConfig, Executor executor) {
if (sessionConfig == null) {
throw new IllegalArgumentException("sessionConfig");
}
if (getTransportMetadata() == null) {
throw new IllegalArgumentException("TransportMetadata");
}
if (!getTransportMetadata().getSessionConfigType().isAssignableFrom(sessionConfig.getClass())) {
throw new IllegalArgumentException("sessionConfig type: " + sessionConfig.getClass() + " (expected: "
+ getTransportMetadata().getSessionConfigType() + ")");
}
// Create the listeners, and add a first listener : a activation listener
// for this service, which will give information on the service state.
listeners = new IoServiceListenerSupport(this);
listeners.add(serviceActivationListener);
// Stores the given session configuration
this.sessionConfig = sessionConfig;
// Make JVM load the exception monitor before some transports
// change the thread context class loader.
ExceptionMonitor.getInstance();
if (executor == null) {
this.executor = Executors.newCachedThreadPool();
createdExecutor = true;
} else {
this.executor = executor;
createdExecutor = false;
}
threadName = getClass().getSimpleName() + '-' + id.incrementAndGet();
}
只是看一下上面提到的功能,这里多提一下就是 ExceptionMonitor.getInstance(); 有兴趣去看一下org.apache.mina.uti.DefaultExceptionMonitor 很简短,只有一个方法,这里只调用一下就是实例化DefaultExceptionMonitor :
- public void exceptionCaught(Throwable cause) {
- if (cause instanceof Error) {
- throw (Error) cause;
- }
- LOGGER.warn("Unexpected exception.", cause);
- }
public void exceptionCaught(Throwable cause) {
if (cause instanceof Error) {
throw (Error) cause;
}
LOGGER.warn("Unexpected exception.", cause);
}