前言

根据前文我们知道,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的初始化的更多相关文章

  1. Netty源码学习系列之4-ServerBootstrap的bind方法

    前言 今天研究ServerBootstrap的bind方法,该方法可以说是netty的重中之重.核心中的核心.前两节的NioEventLoopGroup和ServerBootstrap的初始化就是为b ...

  2. Netty源码学习系列之1-netty的串行无锁化

    前言 最近趁着跟老东家提离职之后.到新公司报道之前的这段空闲时期,着力研究了一番netty框架,对其有了一些浅薄的认识,后续的几篇文章会以netty为主,将近期所学记录一二,也争取能帮未对netty有 ...

  3. Netty源码学习系列之5-NioEventLoop的run方法

    前言     NioEventLoop的run方法,是netty中最核心的方法,没有之一.在该方法中,完成了对已注册的channel上来自底层操作系统的socket事件的处理(在服务端时事件包括客户端 ...

  4. Netty源码学习系列之1-NioEventLoopGroup的初始化

    前言 NioEventLoopGroup是netty对Reactor线程组这个抽象概念的具体实现,其内部维护了一个EventExecutor数组,而NioEventLoop就是EventExecuto ...

  5. 【Netty源码学习】ServerBootStrap

    上一篇博客[Netty源码学习]BootStrap中我们介绍了客户端使用的启动服务,接下来我们介绍一下服务端使用的启动服务. 总体来说ServerBootStrap有两个主要功能: (1)调用父类Ab ...

  6. Netty 源码学习——EventLoop

    Netty 源码学习--EventLoop 在前面 Netty 源码学习--客户端流程分析中我们已经知道了一个 EventLoop 大概的流程,这一章我们来详细的看一看. NioEventLoopGr ...

  7. Netty 源码分析系列(二)Netty 架构设计

    前言 上一篇文章,我们对 Netty做了一个基本的概述,知道什么是Netty以及Netty的简单应用. Netty 源码分析系列(一)Netty 概述 本篇文章我们就来说说Netty的架构设计,解密高 ...

  8. Netty源码阅读(一) ServerBootstrap启动

    Netty源码阅读(一) ServerBootstrap启动 转自我的Github Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速 ...

  9. JDK源码学习系列05----LinkedList

                                             JDK源码学习系列05----LinkedList 1.LinkedList简介 LinkedList是基于双向链表实 ...

随机推荐

  1. P1680 奇怪的分组(组合数+逆元)

    传送门戳我 首先将n减去所有的Ci,于是是原问题转换为:n个相同的球放入m个不同盒子里,不能为空,求方案数. 根据插空法:n个球,放到m个箱子里去不能为空,也就是有m-1块板子放在n-1个空隙之间 那 ...

  2. 向Redis里存入数据

    实现思路:1.    从Redis缓存获取URL统计网址清单2.    逐条拼凑SQL统计语句,暂时不能支持批量计算,因为按单个网址统计.3.    发送到HIVE JDBC执行SQL并等待返回结果4 ...

  3. 王颖奇 20171010129《面向对象程序设计(java)》第十一周学习总结

    实验十一   集合 实验时间 2018-11-8 1.实验目的与要求 (1) 掌握Vetor.Stack.Hashtable三个类的用途及常用API: (2) 了解java集合框架体系组成: (3)  ...

  4. 某科学的PID算法学习笔记

    最近,在某社团的要求下,自学了PID算法.学完后,深切地感受到PID算法之强大.PID算法应用广泛,比如加热器.平衡车.无人机等等,是自动控制理论中比较容易理解但十分重要的算法. 下面是博主学习过程中 ...

  5. 【HBase】协处理器是什么?又能干什么?怎么用?

    目录 简单了解 官方帮助文档 协处理器出现的原因 协处理器的分类 Observer Endpoint Phoenix 协处理器的使用 加载方式 静态加载 动态加载 协处理器的卸载 协处理器Observ ...

  6. VA01信贷使用

    1业务场景 业务在正式机中发现,当使用VA01输入客户编号回车后会报错 2解决方法 1. SE24进入CL_IM_UKM_SD_FSCM_INTEGR1 2. 双击方法IF_EX_BADI_SD_CM ...

  7. GAN的前身——VAE模型原理

    GAN的前身——VAE模型 今天跟大家说一说VAE模型相关的原理,首先我们从判别模型和生成模型定义开始说起: 判别式模型:已知观察变量X和隐含变量z,它对p(z|X)进行建模,它根据输入的观察变量X得 ...

  8. [hdu5254]BFS

    题意:如果一个格子的相邻四个格子中存在两个格子被标记,且这两个格子有公共点,那么这个格子也被标记.给定初始的标记状态,求最终有多少个格子被标记了 思路: 依次对每个格子进行处理,看它能否”生成“新的被 ...

  9. LUNIX命令集

    Linux 是一套免费使用和自由传播的类 Unix 操作系统,是一个基于 POSIX 和 UNIX 的多用户.多任务.支持多线程和多 CPU 的操作系统. Linux 能运行主要的 UNIX 工具软件 ...

  10. shell 并行运行。

    我实在是太喜欢这个方法了.爽歪歪. 原帖 http://www.xaprb.com/blog/2009/05/01/an-easy-way-to-run-many-tasks-in-parallel/ ...