首先是我们一段用户的代码
public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childOption(ChannelOption.TCP_NODELAY, true)
.childAttr(AttributeKey.newInstance("childAttr"), "childAttrValue")
.handler(new ServerHandler())
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) {
ch.pipeline().addLast(new AuthHandler());
//..
}
});
ChannelFuture f = b.bind(8888).sync();
f.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
我们分以下步骤分析源码:
1、通过什么方式创建服务端channel。
2、 创建服务端channel的时候做了什么事情。
通过什么方式创建服务端channel
从bind方法进入:层层深入,到了doBind方法,里面有一个initAndRegister()方法(在AbstractBootstrap类里面):
final ChannelFuture initAndRegister() {
Channel channel = null;
try {
channel = this.channelFactory.newChannel();
this.init(channel);
} catch (Throwable var3) {
if(channel != null) {
channel.unsafe().closeForcibly();
}
return (new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE)).setFailure(var3);
}
...
}
也就是有一个channelFactory类工厂,产生我们的Channel。具体这个channelFactory的实现是什么?我们目前先猜测是ReflectiveChannelFactory,进入ReflectiveChannelFactory的newChannel()方法,明显是使用反射的实现:
public T newChannel() {
try {
return (Channel)this.clazz.newInstance();
} catch (Throwable var2) {
throw new ChannelException("Unable to create Channel from class " + this.clazz, var2);
}
}
那么这个clazz是什么?带着这两个疑问,来到用户代码的这一行:
.channel(NioServerSocketChannel.class)
这一行好像和clazz有关。进入bind方法:
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)));
}
}
看channelFactory方法,一直点进去,就是把传入的ReflectiveChannelFactory传递给AbstractBootstrap类,作为他的其中一个成员变量,这里就解释了前面的channelFactory的实现是什么,就是ReflectiveChannelFactory。
那么我们进入new ReflectiveChannelFactory(channelClass)看看它做了什么:
public ReflectiveChannelFactory(Class<? extends T> clazz) {
if(clazz == null) {
throw new NullPointerException("clazz");
} else {
this.clazz = clazz;
}
}
很明显,刚刚的clazz就是我们用户传进去的NioServerSocketChannel.class
这里,创建服务端channel也就是NioServerSocketChannel的代码已经清晰了
创建服务端channel的时候做了什么事情
我们点进去NioServerSocketChannel这个类,看它的构造方法,也就是在构造的时候做了什么事情:
无参构造器:
public NioServerSocketChannel() {
this(newSocket(DEFAULT_SELECTOR_PROVIDER));
}
DEFAULT_SELECTOR_PROVIDER的来源:
private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();
newSocket的来源:
private static java.nio.channels.ServerSocketChannel newSocket(SelectorProvider provider) {
try {
return provider.openServerSocketChannel();
} catch (IOException var2) {
throw new ChannelException("Failed to open a server socket.", var2);
}
}
这些其实都是使用jdk底层构造ServerSocketChannel的方法创建的。
接下去看无参构造器调用一个参数的构造器:
public NioServerSocketChannel(java.nio.channels.ServerSocketChannel channel) {
super((Channel)null, channel, 16);
this.config = new NioServerSocketChannel.NioServerSocketChannelConfig(this, this.javaChannel().socket());
}
这里主要做了两件事情:
1、调用父类的构造器
2、初始化一个NioServerSocketChannelConfig,以后可以使用这个tcp参数设置类。
第二点可以不用解释了,第一点层层进入,到了AbstractNioChannel(这个AbstractNioChannel是服务端和客户端channel的基类,一些公共的东西都在这个类里面创建)的这个构造方法:
protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
super(parent);
this.ch = ch;
this.readInterestOp = readInterestOp;
try {
ch.configureBlocking(false);
} catch (IOException e) {
try {
ch.close();
} catch (IOException e2) {
if (logger.isWarnEnabled()) {
logger.warn(
"Failed to close a partially initialized socket.", e2);
}
}
throw new ChannelException("Failed to enter non-blocking mode.", e);
}
}
首先把ch传入,然后把readInterestOp也传入,然后是一个nio编程很常用的设置,设置为非阻塞模式:
ch.configureBlocking(false);
最后我们查看第一行super(parent);
protected AbstractChannel(Channel parent) {
this.parent = parent;
id = newId();
unsafe = newUnsafe();
pipeline = newChannelPipeline();
}
也就是为这个服务端channel添加一个id,一个unsafe、一个pipeline。
自此,我们创建服务端channel的源码已经分析完,记住这些东西,以后会串起来。