Netty 5.0源码分析-Bootstrap
1. 前言
io.netty.bootstrap
类包提供包含丰富API的帮助类,能够非常方便的实现典型的服务器端和客户端通道初始化功能。
包含的接口类:
//提供工厂类的newChannel方法创建一个新的Channel。触发事件为:
// -Bootstrap.bind()
// -Bootstrap.connect()
// -ServerBootstrap.bind()
ChannelFactory<T extends Channel>
//创建一个新Channel的工厂类。触发事件为:
// -Bootstrap.bind()
// -Bootstrap.connect()
// -ServerBootstrap.bind()
ServerChannelFactory<T extends ServerChannel>
包含的类为:
//提供简易方式启动一个Channel的帮助类。
//通过支持方法链(method-chaining)使AbstractBootstrap的配置更加简单。
AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel>
//为客户端提供简易的方法去启动一个Channel
Bootstrap
//为服务器端提供简易的方法去启动一个ServerChannel。
ServerBootstrap
2. 接口的实现细节
2.1 ChannelFactory
声明
ChannelFactory仅包含一个方法:T newChannel(eventLoop)
。其中,
T 表示创建的Channel类型;
eventLoop 表示注册在该channel上的处理所有I/O操作的事件循环模型。
实现
ChannelFactory的实现类是BootstrapChannelFactory
,它是一个不可变的final类,实现了接口的newChannel
方法,利用反射创建Channel实例。源码如下:
@Override
public T newChannel(EventLoop eventLoop) {
try {
Constructor<? extends T> constructor = clazz.getConstructor(EventLoop.class);
return constructor.newInstance(eventLoop);
} catch (Throwable t) {
throw new ChannelException("Unable to create Channel from class " + clazz, t);
}
}
2.2 ServerChannelFactory
声明
ServerChannelFactory仅包含一个方法:T newChannel(eventLoop, childGroup)
,其中,
T 表示创建的ServerChannel类型;
EventLoop 表示处理所有网络连接操作的父事件循环模型;
EventLoopGroup 表示处理所有网络I/O操作的子时间循环模型。
实现
ServerChannelFactory的实现类是ServerBootstrapChannelFactory
,它是一个不可变的final类,实现了接口的newChannel
方法,利用反射创建ServerChannel实例。源码如下:
@Override
public T newChannel(EventLoop eventLoop, EventLoopGroup childGroup) {
try {
Constructor<? extends T> constructor = clazz.getConstructor(EventLoop.class, EventLoopGroup.class);
return constructor.newInstance(eventLoop, childGroup);
} catch (Throwable t) {
throw new ChannelException("Unable to create Channel from class " + clazz, t);
}
}
3. 类的实现细节
3.1 AbstractBootstrap
AbstractBootstrap类的基本属性如下表所示:
属性 | 含义 |
---|---|
group | 特殊的事件处理执行器,在其上注册Channel处理异步任务的事件循环 |
handler | channel上的I/O事件处理器,事件能够在其中的ChannelPipeline中流动 |
localAddress | 网络套接字地址 |
options | channel通道的参数配置 |
attrs | bootstrap的属性配置 |
AbstractBootstrap提供了Bootstrap
和ServerBootstrap
的公共的抽象方法实现。
基本的方法列表
public B group(EventLoopGroup group) //为group属性赋值
public B handler(ChannelHandler handler) //为handler属性赋值
public B localAddress(SocketAddress localAddress) //为localAddress属性赋值,另外提供了其他几种localAddress赋值方法,满足不同的实现需求。
public <T> B option(ChannelOption<T> option, T value) //为option属性赋值
public <T> B attr(AttributeKey<T> key, T value) //为attr属性赋值
初始化和注册方法initAndRegister
AbstractBootstrap提供的最重要的方法就是initAndRegister
。该方法的处理流程如下:
1,创建channel通道,动态调用Bootstrap
还是ServerBootstrap
的createChannel
方法通过channelFactory
工厂模式生成Channel对象;
2,根据bootstrap是Bootstrap
还是ServerBootstrap
来调用init(channel)
,主要实现将bootstrap的事件处理器handler添加到channel的事件处理链pipeline、将bootstrap的options和attrs属性配置到channel的ChannelConfig属性和attrs属性;
3,生成ChannelPromise对象regFuture,将其注册到channel上,用来获取事件处理完成后的返回结果(异步阻塞方式);
4,返回处理结果值ChannelFuture。
源代码实现如下:
final ChannelFuture initAndRegister() {
Channel channel;
try {
channel = createChannel();
} catch (Throwable t) {
return VoidChannel.INSTANCE.newFailedFuture(t);
}
try {
init(channel);
} catch (Throwable t) {
channel.unsafe().closeForcibly();
return channel.newFailedFuture(t);
}
ChannelPromise regFuture = channel.newPromise();
channel.unsafe().register(regFuture);
if (regFuture.cause() != null) {
if (channel.isRegistered()) {
channel.close();
} else {
channel.unsafe().closeForcibly();
}
}
return regFuture;
}
服务器端的bind方法
主要利用initAndRegister
中配置的channel、regFuture和localAddress属性值启动channel事件处理循环模型eventLoop的执行器Executor,用来绑定地址,异步阻塞接受事件请求,利用ChannelFutureListener监听事件是否执行完成,返回事件的成功或失败的结果。
源代码实现如下:
private static void doBind0(
final ChannelFuture regFuture, final Channel channel,
final SocketAddress localAddress, final ChannelPromise promise) {
// This method is invoked before channelRegistered() is triggered. Give user handlers a chance to set up
// the pipeline in its channelRegistered() implementation.
channel.eventLoop().execute(new Runnable() {
@Override
public void run() {
if (regFuture.isSuccess()) {
channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
} else {
promise.setFailure(regFuture.cause());
}
}
});
}
3.2 Bootstrap
Bootstrap继承自AbstractBootstrap,其类的形式如下所示:
public final class Bootstrap extends AbstractBootstrap<Bootstrap, Channel>
这样,除了拥有AbstractBootstrap的属性值和方法外,它还包含两个属性值:channelFactory
和remoteAddress
。
channel方法
Bootstrap最重要的目的在于为客户端程序启动一个Channel,为各种异步事件提供处理机制。Channel方法采用工厂模式来生成新的Channel对象。主要流程如下:
1,调用Bootstrap.channel(chanelClass),在其中调用channelFactory(channelFactory);
2,channelFactory的参数调用BootstrapChannelFactory的构造函数生成ChannelFactory对象;
3,记录下Channel对象的构造工厂对象channelFactory。
其实在Bootstrap创建的过程中,调用channel方法并没有立刻得到channel对象,而是得到channel的工厂模式对象channelFactory,真正创建channel对象是在调用Bootstrap.connect()
方法时,触发initAndRegister()
,然后执行createChannel()
方法,最终利用工厂模式对象channelFactory生成Channel对象。
createChannel的源代码如下:
@Override
Channel createChannel() {
EventLoop eventLoop = group().next();
return channelFactory().newChannel(eventLoop);
}
newChannel调用BootstrapChannelFactory.newChannel
来真正生成channel对象,其源代码如下:
@Override
public T newChannel(EventLoop eventLoop) {
try {
Constructor<? extends T> constructor = clazz.getConstructor(EventLoop.class);
return constructor.newInstance(eventLoop);
} catch (Throwable t) {
throw new ChannelException("Unable to create Channel from class " + clazz, t);
}
}
注:T代表继承自Channel
的泛型。
3.3 ServerBootstrap
ServerBootstrap继承自AbstractBootstrap,其类的形式如下所示:
public final class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, ServerChannel>
除了拥有AbstractBootstrap的属性值和方法外,为了支持主从工作模式,提供了子事件处理模型所需要的属性:childOptions、childAttrs、childGroup、childHandler。
为了创建channel对象,提供了工厂模式对象属性:channelFactory。
ServerBootstrap构造函数需要考虑主EventLoop和从EventLoop,在ServerBootstrap(bootstrap)的实现里,主从启动器共用相同的属性。不过,这种方式不常用。一般而言,我们会分别设置主EventLoop和从EventLoop的事件处理模型属性,主EventLoop主要接受各种请求,从EventLoop主要处理各种请求。
基本属性方法
ServerBootstrap的父Channel的属性设置通过继承AbstractBootstrap抽象类实现,子Channel的属性设置通过下标中提供的方法实现:
方法 | 含义 |
---|---|
childOption(ChannelOption childOption, T value) | 设置childOptions属性 |
childAttr(AttributeKey childKey, T value) | 设置childAttrs属性 |
group(EventLoopGroup parentGroup, EventLoopGroup childGroup) | 设置childGroup属性 |
childHandler(ChannelHandler childHandler) | 设置childHandler属性 |
group方法
设置主从Channel的事件处理模型EventExecutorGroup,用于处理所有的事件和I/O操作。源代码如下:
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
super.group(parentGroup);
if (childGroup == null) {
throw new NullPointerException("childGroup");
}
if (this.childGroup != null) {
throw new IllegalStateException("childGroup set already");
}
this.childGroup = childGroup;
return this;
}
可见,其分别设置主EventLoop和从EventLoop的事件处理模型。
channel方法
ServerBootstrap最重要的目的在于为服务器端程序启动一个Channel,为各种异步事件提供处理机制。Channel方法采用工厂模式来生成新的Channel对象。主要流程如下:
1,调用Bootstrap.channel(chanelClass),在其中调用channelFactory(channelFactory);
2,channelFactory的参数调用ServerBootstrapChannelFactory的构造函数生成ChannelFactory对象;
3,记录下ServerChannel对象的构造工厂对象channelFactory。
其实在ServerBootstrap创建的过程中,调用channel方法并没有立刻得到channel对象,而是得到ServerChannel的工厂模式对象channelFactory,真正创建channel对象是在调用ServerBootstrap.bind()
方法时,触发initAndRegister()
,然后执行createChannel()
方法,最终利用工厂模式对象channelFactory生成Channel对象。
createChannel的源代码如下:
@Override
Channel createChannel() {
EventLoop eventLoop = group().next();
return channelFactory().newChannel(eventLoop, childGroup);
}
newChannel调用BootstrapChannelFactory.newChannel
来真正生成channel对象,其源代码如下:
@Override
public T newChannel(EventLoop eventLoop, EventLoopGroup childGroup) {
try {
Constructor<? extends T> constructor = clazz.getConstructor(EventLoop.class, EventLoopGroup.class);
return constructor.newInstance(eventLoop, childGroup);
} catch (Throwable t) {
throw new ChannelException("Unable to create Channel from class " + clazz, t);
}
}
注:T代表继承自ServerChannel
的泛型。
(END)
Netty 5.0源码分析-Bootstrap的更多相关文章
- Netty 5.0源码分析-ByteBuf
1. 概念 Java NIO API自带的缓冲区类功能相当有限,没有经过优化,使用JDK的ByteBuffer操作更复杂.故而Netty的作者Trustin Lee为了实现高效率的网络传输,重新造轮子 ...
- Netty 5.0源码分析之综述
1. 前言 本系列主要是用于梳理Netty的架构流程,深入设计细节,重点关注Netty是如何实现它所声称的特性. (ps:本人水平有限,如有错误,请不吝指教 : )) 2. 什么是Netty Nett ...
- Netty 核心组件 Pipeline 源码分析(二)一个请求的 pipeline 之旅
目录大纲: 前言 针对 Netty 例子源码做了哪些修改? 看 pipeline 是如何将数据送到自定义 handler 的 看 pipeline 是如何将数据从自定义 handler 送出的 总结 ...
- AFNetWorking3.0源码分析
分析: AFNetWorking(3.0)源码分析(一)——基本框架 AFNetworking源码解析 AFNetworking2.0源码解析<一> end
- Solr5.0源码分析-SolrDispatchFilter
年初,公司开发法律行业的搜索引擎.当时,我作为整个系统的核心成员,选择solr,并在solr根据我们的要求做了相应的二次开发.但是,对solr的还没有进行认真仔细的研究.最近,事情比较清闲,翻翻sol ...
- Solr4.8.0源码分析(25)之SolrCloud的Split流程
Solr4.8.0源码分析(25)之SolrCloud的Split流程(一) 题记:昨天有位网友问我SolrCloud的split的机制是如何的,这个还真不知道,所以今天抽空去看了Split的原理,大 ...
- Solr4.8.0源码分析(24)之SolrCloud的Recovery策略(五)
Solr4.8.0源码分析(24)之SolrCloud的Recovery策略(五) 题记:关于SolrCloud的Recovery策略已经写了四篇了,这篇应该是系统介绍Recovery策略的最后一篇了 ...
- Solr4.8.0源码分析(23)之SolrCloud的Recovery策略(四)
Solr4.8.0源码分析(23)之SolrCloud的Recovery策略(四) 题记:本来计划的SolrCloud的Recovery策略的文章是3篇的,但是没想到Recovery的内容蛮多的,前面 ...
- Solr4.8.0源码分析(22)之SolrCloud的Recovery策略(三)
Solr4.8.0源码分析(22)之SolrCloud的Recovery策略(三) 本文是SolrCloud的Recovery策略系列的第三篇文章,前面两篇主要介绍了Recovery的总体流程,以及P ...
随机推荐
- ajax提交表单 验证
function submitKH(mobileInputId,nameInputId) { var mobileInputSelector ='#'+ mobileInputId; var pass ...
- C# 语言的两个html解析器
基于C# 语言的两个html解析器 基于C# 语言的两个html解析器 1)Html Agility Pack http://nsoup.codeplex.com/ 代码段示例: HtmlDocu ...
- MySql处理数据库和表
show databases; mysql> show databases; mysql> create database db_test; Query OK, 1 row affecte ...
- c#自带压缩类实现数据库表导出到CSV压缩文件
c#自带压缩类实现数据库表导出到CSV压缩文件的方法 在导出大量CSV数据的时候,常常体积较大,采用C#自带的压缩类,可以方便的实现该功能,并且压缩比例很高,该方法在我的开源工具DataPie中已经经 ...
- SQLServer数据库误删数据找回
记一次SQLServer数据库误删数据找回 昨天 同事在本机清理数据库表时,连接到了生产机,误删了二十几张表,幸好是晚上加班的时候删除的,生产机上当时是一天一备份,还原备份是最后的策略,最关键的还是要 ...
- JavaScript里的依赖注入
JavaScript里的依赖注入 我喜欢引用这句话,“程序是对复杂性的管理”.计算机世界是一个巨大的抽象建筑群.我们简单的包装一些东西然后发布新工具,周而复始.现在思考下,你所使用的语言包括的一些内建 ...
- C#使用文件监控对象FileSystemWatcher 实现数据同步
在C#使用文件监控对象FileSystemWatcher 实现数据同步 2013-12-12 18:24 by 幕三少, 352 阅读, 3 评论, 收藏, 编辑 最近在项目中有这么个需求,就是得去实 ...
- Dirichlet's Theorem on Arithmetic Progression
poj3006 Dirichlet's Theorem on Arithmetic Progressions 很显然这是一题有关于素数的题目. 注意数据的范围,爆搜超时无误. 这里要用到筛选法求素数. ...
- AngularJS的初始化
AngularJS的初始化 本文主要介绍AngularJS的自动初始化以及在必要的适合如何手动初始化. Angular <script> Tag 下面通过一小段代码来介绍推荐的自动初始化过 ...
- PHP GD 库 缩略图 添加水印
class cls_image { var $error_no = 0; var $error_msg = ''; //var $images_dir = IMAGE_DIR; //var $data ...