本文基于netty-4.0.19.Final包
本文使用netty事例包中的EchoServer.java类来进行分析
先看EchoServer.java中run方法代码
public void run() throws Exception { // Configure the server. EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 100) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast( //new LoggingHandler(LogLevel.INFO), new EchoServerHandler()); } }); // Start the server. ChannelFuture f = b.bind(port).sync(); // Wait until the server socket is closed. f.channel().closeFuture().sync(); } finally { // Shut down all event loops to terminate all threads. bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } }
为什么两个group?它们有什么作用?为什么一个handler?为什么又来一个childHandler?
先不管它,直接看重点的bind方法
进入bind方法后,最终会调用到AbstractBootstrap.java中doBind方法,然后调用initAndRegister方法
final ChannelFuture regFuture = initAndRegister();
进入initAndRegister方法后,发现先生成了一个新的channel
final Channel channel = channelFactory().newChannel();
channelFactory如何创建的?
在EchoServer.java中run方法中发现调用了一个channel方法,channel方法中就会调用channelFactory创建
BootstrapChannelFactory对象的实例,由于是调用的channelFactory().newChannel()方法,我们进入BootstrapChannelFactory类查看newChannel方法,会发现其实是通过反射创建了一个NioServerSocketChannel类的实例
public T newChannel() { try { return clazz.newInstance(); } catch (Throwable t) { throw new ChannelException("Unable to create Channel from class " + clazz, t); } }
接着看initAndRegister方法
initAndRegister方法中调用了init方法,查看发现init方法是抽象方法,在ServerBootstrap类中实现
try { init(channel); } catch (Throwable t) { channel.unsafe().closeForcibly(); return channel.newFailedFuture(t); }
查看ServerBootstrap类的init方法,发现做了两件事情
1、设置了options和attrs,这两个选项在EchoServer类的run方法中没有调用,先忽略
2、在channel的pipeline中增加了两个ChannelHandler,第一个是EchoServer类的run方法中指定的LoggingHandler,第二个是ChannelInitializer
继续看initAndRegister方法
调用group的register方法,而group其实是EchoServer类中run方法中调用group方法设置的NioEventLoopGroup,另外一个为group为childGroup,是定义在ServerBootstrap类中变量,目前还没有用到。
在NioEventLoopGroup方法中查找register方法,发现在父类MultithreadEventLoopGroup中有定义,于是我们跳到了MultithreadEventLoopGroup类的register方法中
MultithreadEventLoopGroup中register方法很简单,委派给EventLoop的register方法,而获取EventLoop是通过调用父类的next方法来做到的
@Override public EventLoop next() { return (EventLoop) super.next(); } @Override public ChannelFuture register(Channel channel) { return next().register(channel); }现在我们来到了父类MultithreadEventExecutorGroup的next方法中