在AbstractBootStrap类的initAndRegister()方法中,先进行对Channel的初始化,在初始化过程结束之后,会执行Channel的注册流程逻辑。如下图:
上图所示源码中,ChannelFuture regFuture = config().group().register(channel);执行Channel注册到EventLoop 上的流程。
1. config()方法
先看该行代码中的第一个方法config():
该方法是一个抽象方法,返回的是AbstractBootstrapConfig类,它可以获取到bootstrap的当前配置。该抽象方法在AbstractBootstrapConfig的子类Bootstrap和ServerBootstrap中实现。这里着重看一下ServerBootStrap中的实现:
返回了一个成员变量config,
是一个ServerBootstrapConfig类,该类包含了ServerBootstrap的所有配置。
2.group()方法

该方法返回一个已经配置的EventLoopGroup类,如果还未配置,则返回null。
3.register(Channel channel)方法

在该EventLoop方法上注册一个Channel,注册完成后,返回的ChannelFuture将收到通知。因为NioEventLoopGroup继承了MultiThreadEventLoopGroup,所以在使用NioEventLoopGroup进行编程时,框架内部调用的是MultiThreadEventLoopGroup的register方法。
3.1 next()方法

next()方法返回一个EventLoop,内部调用了父类的next()方法。看一下父类MultithreadEventExecutorGroup的next()方法。
又调用了chooser.next(),chooser是个啥玩意呢?继续看源码:
这玩意是一个工厂类中的内部类:
里面就一个方法next(),用来创建一个新的EventExecutor。这个EventExecutorChooserFactory有一个实现类DefaultEventExecutorChooserFactory,该类主要使用简单轮询方法选择下一个Executor,里面的newChooser()方法是这样实现的:
意思就是如果参数的长度是2的幂,那么就返回一个PowerOfTwoEventExecutorChooser,否则就返回一个GenericEventExecutorChooser,主要是用于提升性能,这里也可以看出netty这个框架对于性能的追求已经趋于极致了,这么小的细节都考虑到了性能问题。
看一下GenericEventExecutorChooser.next()方法的实现,实际上就是在对Executor[]的长度取模。找下一个EventExecutor
3.2 next().register()
在上面我们看到在开始执行注册流程时调用的是 MultiThreadEventLoopGroup.register() 方法,其内部调用了next().register(channel)方法,这里next()返回一个EventLoop,也就是调用了EventLoop.register,具体实现方法是SingleThreadEventLoopGroup.register(),
随后执行SingleThreadEventLoopGroup重载的一个register()方法:
先检查传入的参数是否为null,promise.channel().unsafe()返回一个Unsafe,执行底层的register()方法,该方法实现在AbstractChannel中的内部类AbstractUnsafe中。
@Override
public final void register(EventLoop eventLoop, final ChannelPromise promise) {
//1.检查eventLoop是否为空
if (eventLoop == null) {
throw new NullPointerException("eventLoop");
}
//2.检查是否已经注册,如果已经注册,抛出异常
if (isRegistered()) {
promise.setFailure(new IllegalStateException("registered to an event loop already"));
return;
}
//3.检查参数是否是给定类的实例或是其子类的实例
if (!isCompatible(eventLoop)) {
promise.setFailure(
new IllegalStateException("incompatible event loop type: " + eventLoop.getClass().getName()));
return;
}
AbstractChannel.this.eventLoop = eventLoop;
//4.检查执行的线程是否是当前的线程,如果是则不存在并发问题,
//如果不是当前线程则则将注册流程放到任务队列中执行
if (eventLoop.inEventLoop()) {
register0(promise);
} else {
try {
eventLoop.execute(new Runnable() {
@Override
public void run() {
register0(promise);
}
});
} catch (Throwable t) {
logger.warn(
"Force-closing a channel whose registration task was not accepted by an event loop: {}",
AbstractChannel.this, t);
closeForcibly();
closeFuture.setClosed();
safeSetFailure(promise, t);
}
}
}
接下来看register0():
private void register0(ChannelPromise promise) {
try {
// check if the channel is still open as it could be closed in the mean time when the register
// call was outside of the eventLoop
if (!promise.setUncancellable() || !ensureOpen(promise)) {
return;
}
boolean firstRegistration = neverRegistered;
//register的具体实现
doRegister();
neverRegistered = false;
registered = true;
// Ensure we call handlerAdded(...) before we actually notify the promise. This is needed as the
// user may already fire events through the pipeline in the ChannelFutureListener.
pipeline.invokeHandlerAddedIfNeeded();
safeSetSuccess(promise);
//调用下一个channelInboundHandler的channelRegistered()方法。
pipeline.fireChannelRegistered();
// Only fire a channelActive if the channel has never been registered. This prevents firing
// multiple channel actives if the channel is deregistered and re-registered.
//所谓isActive就是指Channel处于活动 状态,已经连接或者绑定并且已经就绪
if (isActive()) {
if (firstRegistration) {
//调用下一个channelInbooundHandler的channelActive()方法
pipeline.fireChannelActive();
} else if (config().isAutoRead()) {
// This channel was registered before and autoRead() is set. This means we need to begin read
// again so that we process inbound data.
//
// See https://github.com/netty/netty/issues/4805
beginRead();
}
}
} catch (Throwable t) {
// Close the channel directly to avoid FD leak.
closeForcibly();
closeFuture.setClosed();
safeSetFailure(promise, t);
}
}
可以看到,有一个doRegister()方法,该方法定义在AbstractChannel中
具体实现在其子类中,这里着重看AbstractNioChannel中的实现:
@Override
protected void doRegister() throws Exception {
boolean selected = false;
for (;;) {
try {
//1.javaChannel()返回java nio中的SelectableChannel,
//eventLoop().unwrappedSelector()返回jdk中的Selector
selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
return;
} catch (CancelledKeyException e) {
if (!selected) {
// Force the Selector to select now as the "canceled" SelectionKey may still be
// cached and not removed because no Select.select(..) operation was called yet.
eventLoop().selectNow();
selected = true;
} else {
// We forced a select operation on the selector before but the SelectionKey is still cached
// for whatever reason. JDK bug ?
throw e;
}
}
}
}
这段代码终于看到Java Nio的身影了.将channel注册到Selector上。