前言bootstrap
根據前文咱們知道,NioEventLoopGroup和NioEventLoop是netty對Reactor線程模型的實現,而本文要說的ServerBootstrap是對上面兩者的整合與調用,是一個統籌者和協調者。具體netty使用的是Reactor單線程模型仍是多線程模型、抑或者主從多線程模型,都是ServerBootstrap的不一樣配置決定的。多線程
下面照例粘貼一下示例demo(以Reactor多線程模式構建),開始正文。socket
1 public class NettyDemo1 { 2 // netty服務端的通常性寫法 3 public static void main(String[] args) { 4 EventLoopGroup boss = new NioEventLoopGroup(1); 5 EventLoopGroup worker = new NioEventLoopGroup(); 6 try { 7 ServerBootstrap bootstrap = new ServerBootstrap(); 8 bootstrap.group(boss, worker).channel(NioServerSocketChannel.class) 9 .option(ChannelOption.SO_BACKLOG, 100) 10 .childHandler(new ChannelInitializer<SocketChannel>() { 11 @Override 12 protected void initChannel(SocketChannel socketChannel) throws Exception { 13 ChannelPipeline pipeline = socketChannel.pipeline(); 14 pipeline.addLast(new StringDecoder()); 15 pipeline.addLast(new StringEncoder()); 16 pipeline.addLast(new NettyServerHandler()); 17 } 18 }); 19 ChannelFuture channelFuture = bootstrap.bind(90); 20 channelFuture.channel().closeFuture().sync(); 21 } catch (Exception e) { 22 e.printStackTrace(); 23 } finally { 24 boss.shutdownGracefully(); 25 worker.shutdownGracefully(); 26 } 27 } 28 }
1、ServerBootstrap的初始化ide
ServerBootstrap的無參構造器啥都沒作,它使用的build模式給屬性賦值,即上面示例中看到的,每執行一個賦值方法都會返回當前對象的引用使得能夠繼續鏈式調用。下面挨個方法追蹤。oop
1 public ServerBootstrap() { }
一、ServerBootstrap.group方法ui
ServerBootstrap有兩個可用重載group方法(以下的兩個),其中接收一個group入參的方法會調用有兩個入參的group方法,只是兩個參數傳同一個group。這兩個group方法決定了netty使用的Reactor線程模型的類型,一個group入參的方法對應Reactor單線程模型,兩個入參且不是同一個group的方法對應Reactor多線程模型或主從多線程模型(具體是哪種取決於實例化parentGroup時的線程數)。此處只是提一下,先有個印象,後面會對線程模型進行詳細研究。this
1 public ServerBootstrap group(EventLoopGroup group) { 2 return group(group, group); 3 }
1 public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) { 2 super.group(parentGroup); 3 ObjectUtil.checkNotNull(childGroup, "childGroup"); 4 if (this.childGroup != null) { 5 throw new IllegalStateException("childGroup set already"); 6 } 7 this.childGroup = childGroup; 8 return this; 9 }
能夠看到上述group方法對兩個入參進行了不一樣位置的賦值,將第一個參數parentGroup傳給了父類AbstractBootstrap的group方法,以下,即最終賦值給了AbstractBootstrap中的group屬性。第二個參數直接賦值給了ServerBootstrap的childGroup屬性。spa
1 public B group(EventLoopGroup group) { 2 ObjectUtil.checkNotNull(group, "group"); 3 if (this.group != null) { 4 throw new IllegalStateException("group set already"); 5 } 6 this.group = group; 7 return self(); 8 }
二、ServerBootstrap.option/childOption方法和ServerBootstrap.attr/childAttr方法線程
這四個方法只是作了屬性的賦值,分別賦值給了AbstractBootstrap的options屬性和attrs屬性以及ServerBootstrap的childOptions屬性和childAttrs屬性。netty
1 public <T> B option(ChannelOption<T> option, T value) { 2 ObjectUtil.checkNotNull(option, "option"); 3 if (value == null) { 4 synchronized (options) { 5 options.remove(option); 6 } 7 } else { 8 synchronized (options) { 9 options.put(option, value); 10 } 11 } 12 return self(); 13 }
1 public <T> B attr(AttributeKey<T> key, T value) { 2 ObjectUtil.checkNotNull(key, "key"); 3 if (value == null) { 4 synchronized (attrs) { 5 attrs.remove(key); 6 } 7 } else { 8 synchronized (attrs) { 9 attrs.put(key, value); 10 } 11 } 12 return self(); 13 }
三、ServerBootstrap.channel方法
調用的是父類AbstractBootstrap的channel方法:
1 public B channel(Class<? extends C> channelClass) { 2 return channelFactory(new ReflectiveChannelFactory<C>( 3 ObjectUtil.checkNotNull(channelClass, "channelClass") 4 )); 5 }
能夠看到先封裝成了一個ReflectiveChannelFactory對象,而後調用channelFactory方法,下面挨個看。ReflectiveChannelFactory的構造器以下,可見就是將傳入class對象的構造器取出來賦值,此時constructor存放的就是NioServerSocketChannel的構造器。
public ReflectiveChannelFactory(Class<? extends T> clazz) { ObjectUtil.checkNotNull(clazz, "clazz"); try { this.constructor = clazz.getConstructor(); } catch (NoSuchMethodException e) { throw new IllegalArgumentException("Class " + StringUtil.simpleClassName(clazz) + " does not have a public non-arg constructor", e); } }
channelFactory方法的工做是將上面建立的ReflectiveChannelFactory對象賦值給AbstractBootstrap的channelFactory屬性:
1 public B channelFactory(ChannelFactory<? extends C> channelFactory) { 2 ObjectUtil.checkNotNull(channelFactory, "channelFactory"); 3 if (this.channelFactory != null) { 4 throw new IllegalStateException("channelFactory set already"); 5 } 6 7 this.channelFactory = channelFactory; 8 return self(); 9 }
四、ServerBootstrap.handler方法和ServerBootstrap.childHandler方法
handler方法的入參賦值給了AbstractBootstrap的handler屬性,childHandler方法的入參賦值給了ServerBootstrap的childHandler屬性。看到這裏想必園友們也能看出ServerBootstrap的賦值規律了,凡是child開頭的都放在ServerBootstrap中,而不帶child的大多放在其父類ABstractBootstrap中。
1 public B handler(ChannelHandler handler) { 2 this.handler = ObjectUtil.checkNotNull(handler, "handler"); 3 return self(); 4 }
1 public ServerBootstrap childHandler(ChannelHandler childHandler) { 2 this.childHandler = ObjectUtil.checkNotNull(childHandler, "childHandler"); 3 return this; 4 }
五、完成賦值後ServerBootstrap的快照圖
小結
ServerBootstrap的初始化過程看起來賦了不少值,但都只是作了準備工做,看起來輕鬆又簡單,但請注意,這是暴風雨前寧靜。前面的各類賦值到底有什麼用處?不少屬性分爲有child前綴和沒有child前綴,這樣設置又有什麼意圖?下一期將進入ServerBootstrap的bind方法,這是netty的深水區,不少謎底也將在這裏獲得揭曉,敬請期待!