Netty源码学习系列之2-ServerBootstrap的初始化
前言
根据前文我们知道,NioEventLoopGroup和NioEventLoop是netty对Reactor线程模型的实现,而本文要说的ServerBootstrap是对上面二者的整合与调用,是一个统筹者和协调者。具体netty使用的是Reactor单线程模型还是多线程模型、抑或者主从多线程模型,都是ServerBootstrap的不同配置决定的。
下面照例粘贴一下示例demo(以Reactor多线程模式构建),开始正文。
public class NettyDemo1 {
// netty服务端的一般性写法
public static void main(String[] args) {
EventLoopGroup boss = new NioEventLoopGroup(1);
EventLoopGroup worker = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(boss, worker).channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 100)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast(new StringDecoder());
pipeline.addLast(new StringEncoder());
pipeline.addLast(new NettyServerHandler());
}
});
ChannelFuture channelFuture = bootstrap.bind(90);
channelFuture.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
boss.shutdownGracefully();
worker.shutdownGracefully();
}
}
}
一、ServerBootstrap的初始化
ServerBootstrap的无参构造器啥都没做,它使用的build模式给属性赋值,即上面示例中看到的,每执行一个赋值方法都会返回当前对象的引用使得可以继续链式调用。下面挨个方法追踪。
public ServerBootstrap() { }
1、ServerBootstrap.group方法
ServerBootstrap有两个可用重载group方法(如下的两个),其中接收一个group入参的方法会调用有两个入参的group方法,只是两个参数传同一个group。这两个group方法决定了netty使用的Reactor线程模型的类型,一个group入参的方法对应Reactor单线程模型,两个入参且不是同一个group的方法对应Reactor多线程模型或主从多线程模型(具体是哪一种取决于实例化parentGroup时的线程数)。此处只是提一下,先有个印象,后面会对线程模型进行详细研究。
public ServerBootstrap group(EventLoopGroup group) {
return group(group, group);
}
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
super.group(parentGroup);
ObjectUtil.checkNotNull(childGroup, "childGroup");
if (this.childGroup != null) {
throw new IllegalStateException("childGroup set already");
}
this.childGroup = childGroup;
return this;
}
可以看到上述group方法对两个入参进行了不同位置的赋值,将第一个参数parentGroup传给了父类AbstractBootstrap的group方法,如下,即最终赋值给了AbstractBootstrap中的group属性。第二个参数直接赋值给了ServerBootstrap的childGroup属性。
public B group(EventLoopGroup group) {
ObjectUtil.checkNotNull(group, "group");
if (this.group != null) {
throw new IllegalStateException("group set already");
}
this.group = group;
return self();
}
2、ServerBootstrap.option/childOption方法和ServerBootstrap.attr/childAttr方法
这四个方法只是做了属性的赋值,分别赋值给了AbstractBootstrap的options属性和attrs属性以及ServerBootstrap的childOptions属性和childAttrs属性。
public <T> B option(ChannelOption<T> option, T value) {
ObjectUtil.checkNotNull(option, "option");
if (value == null) {
synchronized (options) {
options.remove(option);
}
} else {
synchronized (options) {
options.put(option, value);
}
}
return self();
}
public <T> B attr(AttributeKey<T> key, T value) {
ObjectUtil.checkNotNull(key, "key");
if (value == null) {
synchronized (attrs) {
attrs.remove(key);
}
} else {
synchronized (attrs) {
attrs.put(key, value);
}
}
return self();
}
3、ServerBootstrap.channel方法
调用的是父类AbstractBootstrap的channel方法:
public B channel(Class<? extends C> channelClass) {
return channelFactory(new ReflectiveChannelFactory<C>(
ObjectUtil.checkNotNull(channelClass, "channelClass")
));
}
可以看到先封装成了一个ReflectiveChannelFactory对象,然后调用channelFactory方法,下面挨个看。ReflectiveChannelFactory的构造器如下,可见就是将传入class对象的构造器取出来赋值,此时constructor存放的就是NioServerSocketChannel的构造器。
public ReflectiveChannelFactory(Class<? extends T> clazz) {
ObjectUtil.checkNotNull(clazz, "clazz");
try {
this.constructor = clazz.getConstructor();
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException("Class " + StringUtil.simpleClassName(clazz) +
" does not have a public non-arg constructor", e);
}
}
channelFactory方法的工作是将上面创建的ReflectiveChannelFactory对象赋值给AbstractBootstrap的channelFactory属性:
public B channelFactory(ChannelFactory<? extends C> channelFactory) {
ObjectUtil.checkNotNull(channelFactory, "channelFactory");
if (this.channelFactory != null) {
throw new IllegalStateException("channelFactory set already");
}
this.channelFactory = channelFactory;
return self();
}
4、ServerBootstrap.handler方法和ServerBootstrap.childHandler方法
handler方法的入参赋值给了AbstractBootstrap的handler属性,childHandler方法的入参赋值给了ServerBootstrap的childHandler属性。看到这里想必园友们也能看出ServerBootstrap的赋值规律了,凡是child开头的都放在ServerBootstrap中,而不带child的大多放在其父类ABstractBootstrap中。
public B handler(ChannelHandler handler) {
this.handler = ObjectUtil.checkNotNull(handler, "handler");
return self();
}
public ServerBootstrap childHandler(ChannelHandler childHandler) {
this.childHandler = ObjectUtil.checkNotNull(childHandler, "childHandler");
return this;
}
5、完成赋值后ServerBootstrap的快照图

小结
ServerBootstrap的初始化过程看起来赋了很多值,但都只是做了准备工作,看起来轻松又简单,但请注意,这是暴风雨前宁静。前面的各种赋值到底有什么用处?很多属性分为有child前缀和没有child前缀,这样设置又有什么意图?下一期将进入ServerBootstrap的bind方法,这是netty的深水区,很多谜底也将在这里得到揭晓,敬请期待!
Netty源码学习系列之2-ServerBootstrap的初始化的更多相关文章
- Netty源码学习系列之4-ServerBootstrap的bind方法
前言 今天研究ServerBootstrap的bind方法,该方法可以说是netty的重中之重.核心中的核心.前两节的NioEventLoopGroup和ServerBootstrap的初始化就是为b ...
- Netty源码学习系列之1-netty的串行无锁化
前言 最近趁着跟老东家提离职之后.到新公司报道之前的这段空闲时期,着力研究了一番netty框架,对其有了一些浅薄的认识,后续的几篇文章会以netty为主,将近期所学记录一二,也争取能帮未对netty有 ...
- Netty源码学习系列之5-NioEventLoop的run方法
前言 NioEventLoop的run方法,是netty中最核心的方法,没有之一.在该方法中,完成了对已注册的channel上来自底层操作系统的socket事件的处理(在服务端时事件包括客户端 ...
- Netty源码学习系列之1-NioEventLoopGroup的初始化
前言 NioEventLoopGroup是netty对Reactor线程组这个抽象概念的具体实现,其内部维护了一个EventExecutor数组,而NioEventLoop就是EventExecuto ...
- 【Netty源码学习】ServerBootStrap
上一篇博客[Netty源码学习]BootStrap中我们介绍了客户端使用的启动服务,接下来我们介绍一下服务端使用的启动服务. 总体来说ServerBootStrap有两个主要功能: (1)调用父类Ab ...
- Netty 源码学习——EventLoop
Netty 源码学习--EventLoop 在前面 Netty 源码学习--客户端流程分析中我们已经知道了一个 EventLoop 大概的流程,这一章我们来详细的看一看. NioEventLoopGr ...
- Netty 源码分析系列(二)Netty 架构设计
前言 上一篇文章,我们对 Netty做了一个基本的概述,知道什么是Netty以及Netty的简单应用. Netty 源码分析系列(一)Netty 概述 本篇文章我们就来说说Netty的架构设计,解密高 ...
- Netty源码阅读(一) ServerBootstrap启动
Netty源码阅读(一) ServerBootstrap启动 转自我的Github Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速 ...
- JDK源码学习系列05----LinkedList
JDK源码学习系列05----LinkedList 1.LinkedList简介 LinkedList是基于双向链表实 ...
随机推荐
- 在linux上部署自己开发的web项目
在linux上部署自己开发的web项目 前言:相信有很多做开发的小伙伴和我之前一样,只会在windows环境下,利用开发工具开发运行web项目,但是却不知道怎么把开发好的项目部署到linux服务器上去 ...
- B. Sorted Adjacent Differences(思维构造)
\(给出n个数字,要求构造一个由这n个数组成的序列,使得|a_1-a_2|<=|a_2-a_3|...<=|a_{n-1}-a_n|\) \(排序后,从数列中间取个数,然后从左右分别循环取 ...
- 【HBase】Java实现过滤器查询
目录 概述 代码实现 rowKey过滤器RowFilter 列族过滤器FamilyFilter 列过滤器QualifierFilter 列值过滤器ValueFilter 专用过滤器 单列值过滤器 Si ...
- 实现简单网页rtmp直播:nginx+ckplayer+linux
一.安装nginx 安装带有rtmp模块的nginx服务器(其它支持rtmp协议的流媒体服务器像easydarwin.srs等+Apache等web服务器也可以),此处使用nginx服务器,简单方便. ...
- Gitlab升级记
一: 验证gitlab备份是否可用 这里所使用的操作系统环境全部都基于Cetnos7, 防火墙以及selinux全部关闭. 1. 另外找一台机器,安装与服务器版本相同的gitlab,根据原服务器数据的 ...
- JDBC10 Blob二进制对象
//将图片输入到数据库中 // String sql="insert into t_user2 (username,headImg) values (?,?)"; // ps=co ...
- Java UDP小结
UDP: * 发送端 ...
- 设计模式之GOF23中介者模式
中介者模式Mediator 场景:公司中各个部门需要交互,通过中介总经理进行交互 核心: 如果一个系统中对象之间的联系成网状结构,对象之间多对多,将导致关系极其复杂,这些对象统称为“同事关系” 我们可 ...
- [hdu5255]枚举
思路:这题与csu1392题目类似,方法类似.枚举最高位,最低位和中间数字的长度,然后列等式,计算中间的数字,看长度是不是跟枚举的一致,需要注意的是中间数字可以有前导0,如果根据等式算出来的中间数字为 ...
- gets() 、 getchar() 、 getch() 、getche()、gets()、 scanf()的区别
1.getchar().getche().getch() (1).getchar 函数用于从标准输入设备键盘读入单个字符,返回表示读入字符的ASCII码值,并在屏上显示该字符:头文件是 stdio.h ...