本章主要介绍AbstractBootStrap 以及BootStrap,ServerBootStrap 主要运用了建造者模式(bootStrap的构造)以及门面模式(不需要注意细节,屏蔽了)
一:AbstractBootStrap解析:
AbstratBootStrap:channel的工厂setteer方法
public B channelFactory(ChannelFactory<? extends C> channelFactory) { //默认的channelfactory的构造方法
if (channelFactory == null) {
throw new NullPointerException("channelFactory");
} else if (this.channelFactory != null) {
throw new IllegalStateException("channelFactory set already");
} else {
this.channelFactory = channelFactory;
return this.self();
}
}
public B channel(Class<? extends C> channelClass) {
if (channelClass == null) {
throw new NullPointerException("channelClass");
} else {
return this.channelFactory((io.netty.channel.ChannelFactory)(new ReflectiveChannelFactory(channelClass)));
}
}
public interface ChannelFactory<T extends Channel> extends io.netty.bootstrap.ChannelFactory<T> {
T newChannel();
}
ReflectiveChannelFactory class类:
public class ReflectiveChannelFactory<T extends Channel> implements ChannelFacory<T>{
public ReflectiveChannelFactory(Class<? extends T> clazz) {
if (clazz == null) {
throw new NullPointerException("clazz");
} else {
this.clazz = clazz;
}
}
public T newChannel() {
try {
return (Channel)this.clazz.getConstructor().newInstance();// 用于反射调用无参构造方法创建一个Chanel
} catch (Throwable var2) {
throw new ChannelException("Unable to create Channel from class " + this.clazz, var2);
}
}
}
AbstratBootStrap:bind方法:(只有bind而没有connect是因为在serverbootstrap中,会调用abstractBootStrap构造函数,将bossgroup作为group进行bind操作): 用于绑定前述工厂创建的Channel到本地的一个端口
public ChannelFuture bind() {
this.validate();//检验数据的有效性
SocketAddress localAddress = this.localAddress;
if (localAddress == null) {
throw new IllegalStateException("localAddress not set");
} else {
return this.doBind(localAddress);//调用dobind()进行监听服务
}
}
public B validate() {//判断group以及channelFactory是否初始化,是否为null
if (this.group == null) {
throw new IllegalStateException("group not set");
} else if (this.channelFactory == null) {
throw new IllegalStateException("channel or channelFactory not set");
} else {
return this.self();
}
}
AbstratBootStrap:doBind(final SocketAddress localAddress)方法:
Netty的特点是 事件驱动 doBind()的注册和绑定就是两个异步事件,注册是将Channel注册到Reactor线程池,绑定是指Channel获取到了本地的一个TCP端口。
所以Netty源码里大量采用了ChannelFuture。当一个事件完成时,会回调注册到channelfuture上的ChannelFutureListener方法,从而实现异步操作。
Netty4为了简化逻辑处理逻辑,遵循这样一条规则:一个Channel产生的IO事件始终由其注册到的线程处理,可知注册和绑定事件都将在同一个线程也就是Channel注册到的线程执行。
private ChannelFuture doBind(final SocketAddress localAddress) {
final ChannelFuture regFuture = this.initAndRegister();//创建Channel并注册到线程池
final Channel channel = regFuture.channel();
if (regFuture.cause() != null) {//注册失败
return regFuture;
} else if (regFuture.isDone()) {//Channel注册完成并且成功
ChannelPromise promise = channel.newPromise();
doBind0(regFuture, channel, localAddress, promise);
return promise;
} else {//注册是异步事件,有可能此时还未注册完成,可采用异步操作(添加一个监听事件)
final AbstractBootstrap.PendingRegistrationPromise promise = new AbstractBootstrap.PendingRegistrationPromise(channel);
regFuture.addListener(new ChannelFutureListener() {
//该方法会在注册完成时进行调用
public void operationComplete(ChannelFuture future) throws Exception {
Throwable cause = future.cause();
if (cause != null) {
//注册过程时有异常 就失败
promise.setFailure(cause);
} else {
//注册完成并成功
promise.registered();//设置为注册到的线程(源代码返回true?啥意思)
AbstractBootstrap.doBind0(regFuture, channel, localAddress, promise);
}
}
});
return promise;
}
}
initAndRegister()方法主要分为3个部分:
-
创建Channel
-
绑定用户自定义的Handler()
-
将该Channel注册到Reactor中去
//在后面会用一个专门的章节进行解析
final ChannelFuture initAndRegister() {
Channel channel = null;
try {
channel = this.channelFactory.newChannel();//创建一个Channel(看后面的Channel的初始化)
this.init(channel);//初始化Handler(),由子类bootstrap或者serverBootStrap进行实现,可视为一个模板方法
} catch (Throwable var3) {
if (channel != null) {
channel.unsafe().closeForcibly();
return (new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE)).setFailure(var3);
}
//还没有注册到线程池。使用默认线程GlobalEventExecutor
return (new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE)).setFailure(var3);
}
// 将channel注册到Reactor线程池
ChannelFuture regFuture = this.config().group().register(channel);
if (regFuture.cause() != null) {
if (channel.isRegistered()) {
channel.close();
} else {
channel.unsafe().closeForcibly();
}
}
return regFuture;
}
initAndRegister之后,就进行doBind0()操作;
private static void doBind0(final ChannelFuture regFuture, final Channel channel, final SocketAddress localAddress, final ChannelPromise promise) {
channel.eventLoop().execute(new Runnable() {
public void run() {
if (regFuture.isSuccess()) {
channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
} else {
promise.setFailure(regFuture.cause());
}
}
});
}
这个bind过程夹杂很多私货,总结一下流程:
-
使用ChannelFactory创建一个Channel
-
调用init()方法初始化Channel,主要是绑定处理器
-
注册到一个Reactor线程池
-
对注册的异步结果处理:注册成功进行绑定操作,此时绑定失败将会关闭Channel返回异步绑定失败,绑定成功返回异步成功;注册失败直接返回异步注册失败。