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提供了BootstrapServerBootstrap的公共的抽象方法实现。

基本的方法列表

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还是ServerBootstrapcreateChannel方法通过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的属性值和方法外,它还包含两个属性值:channelFactoryremoteAddress

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)

最新文章

  1. 多Linux系统如何复用/home目录
  2. AWS系列之三 使用EBS
  3. Construct Binary Tree from Preorder and Inorder Traversal
  4. Linux 中 Weblogic 启动和关闭
  5. 让finder显示路径
  6. AutoMapper使用笔记
  7. TFS 强制撤销别人签出的代码
  8. # Day04-Android
  9. Android Geocoder(位置解析)
  10. PHP的数据类型和魔术常量
  11. 安装mysql时出现应用程序无法正常启动(0xc000007b)
  12. Go语言学习之11 日志收集系统kafka库实战
  13. zw量化交易·实盘操作·系列培训班
  14. springboot程序无法访问静态资源
  15. Vue.js基础(二)
  16. 解决谷歌浏览器频繁出现adobe flash player因过期而遭到阻止的问题(转自知乎)
  17. VFIO简介 (转载)
  18. 11.@RequestParam @RequestBody @PathVariable 等参数绑定注解详解
  19. 学习笔记:ALTERing a Huge MySQL Table - 对一个超大表做alter调整
  20. 云服务设置多台tomcat开机自启动

热门文章

  1. spring bean范围
  2. hadoop编程技巧(3)---定义自己的区划类别Partitioner
  3. 更新部分字段 NHibernate
  4. NodeJS热部署工具 — supervisor
  5. NUint使用详解及Visual Studio配置
  6. UML基础概念
  7. 基于多重信号分类算法的DOA估计
  8. 集群管理工具Salt
  9. D11
  10. FormsAuthentication知多少