这篇我们就着重的说下 bind 方法,这个方法也是触发 Netty 真正启动的方法。
先打个预防针,源码也不是那么简单的,有时候看着有点绕,如果你想面试的时候胸有成竹,还是得有点耐心的,如果中间没看懂没事,最后我有总结,看完总结之后应该会清晰的。
对了,如果有条件的话,建议在电脑上看这篇文章,会更加舒适。
好了,开局先来一张图,bind 的核心操作就如下图所示,下面长篇的源码分析也是为了说清楚这个流程,所以什么类名,方法名都不重要,重要的是知晓整体流程:
注意,上图的 Channel 指的是 ServerChannel。
bind 的很多方法都是异步执行的,所以有些流程是主线程执行,有些是 eventloop 执行的,这个需要注意下,不然会感觉有点乱。
先看看这张图大体有个印象,然后我们开始盘 bind 方法~
bind 流程
从 bind 方法进入,实际上就会调用父类 AbstractBootstrap#doBind。
我们来简单的看下 doBind 这个方法,要点我都用文字标明了:
可以看到,这个方法主要做了下面这四件事:
- 创建 channel
- 初始化 channel
- 绑定 channel 至 group 内的某个 eventLoop 上
- 绑定端口
下面我会逐一的分析。
创建 channel
先来看下 initAndRegister 方法。
从下面的源码可以看到,这个方法主要就是创建一个 Channel 对象,然后初始化 Channel,最后将它注册到 eventLoop 上。
channelFactory.newChannel() 是利用反射得到一个 Channel 对象。还记得我们构建 ServerBootstrap 时候设置的 channel 类型吗:.channel(NioServerSocketChannel.class)
通过传入的这个 class 就可以得到构造器,然后调用 newInstance 即可得到一个对象。
这样就创建了一个 NioServerSocketChannel 对象。
通过继承链,我们可以发现 NioServerSocketChannel 会调用父类 AbstractChannel 的构造器,而在这里就会创建三个重要的东西: