Netty源碼分析第一章: Server啓動流程html
概述:ide
本章主要講解server啓動的關鍵步驟, 讀者只須要了解server啓動的大概邏輯, 知道關鍵的步驟在哪一個類執行便可, 並不須要瞭解每一步的運做機制, 以後會對每一個模塊進行深度分析oop
第一節:服務端初始化源碼分析
首先看下在咱們用戶代碼中netty的使用最簡單的一個demo:學習
//建立boss和worker線程(1) EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); //建立ServerBootstrap(2) ServerBootstrap b = new ServerBootstrap(); //初始化boss和work線程化兩個線程(3) b.group(bossGroup, workerGroup) //聲明NioServerSocketChannel(4) .channel(NioServerSocketChannel.class) //初始化客戶端Handler(5) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) { ch.pipeline().addLast(new StringDecoder()); ch.pipeline().addLast(new StringEncoder()); ch.pipeline().addLast(new ServerHandler()); } }); //綁定端口(6) ChannelFuture f = b.bind(8888).sync(); f.channel().closeFuture().sync();
相信這段代碼使用過netty的同窗應該都不陌生.這裏每一步都用了註釋和步驟序號進行標註, 爲了方便學習過程當中更容易的定位.每一步的講解, 儘可能本身也去跟到源碼中, 這樣會有個更深入的理解ui
第一步, 建立兩個線程組:this
其中會調用NioEventLoopGroup()的構造方法, 其中的建立邏輯, 並非這章的重點, 在這裏你們只須要知道這裏建立了兩個線程組spa
第二步, 建立ServerBootstrap, 咱們發現, 這裏建立只調用了其無參的構造方法, 緣由很簡單, 就是參數太多, 儘可能要用構造方法去初始化, 而是使用後面的build的方式.net
第三步, 初始化boss和work線程化兩個線程線程
咱們跟到group方法中去看:
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) { //設置線程池組
super.group(parentGroup); this.childGroup = childGroup; return this; }
爲了代碼可讀性, 去掉非關鍵代碼(之後再也不贅述), 咱們看到這裏初始化了自家的屬性childGroup, 而這個屬性就是咱們傳入的worker線程組, 而boss線程組則交給了其父類的group方法去作處理
咱們點進去super.group(parentGroup), 進入到ServerBootstroop的父類AbstractBootstrap的group()方法:
public B group(EventLoopGroup group) { this.group = group; return (B) this; }
看到在其父類初始化了boss線程
咱們看到這個方法返回了this, 也就是ServerBootstroop自身, 這樣經過自身對象不斷的build進行屬性初始化, 以後的方法也是如此
至此, worker和boss兩個線程組初始化完畢
回到最開始的第四步, 再點進到channel(ServerSocketChannel.class)方法當中, 咱們看到AbsractServerBootstrap的channel(Class<? extends C> channelClass)方法:
public B channel(Class<? extends C> channelClass) { return channelFactory(new ReflectiveChannelFactory<C>(channelClass)); }
咱們看到這個這返回的是channelFactory(new ReflectiveChannelFactory<C>(channelClass))方法, 而且傳入一個ReflectiveChannelFactory對象的實例,
咱們能夠跟進去看下ReflectiveChannelFactory的構造方法:
public ReflectiveChannelFactory(Class<? extends T> clazz) { this.clazz = clazz; }
這裏初始化了一個成員變量clazz, 而這個clazz就是用戶代碼調用channel(NioServerSocketChannel.class)傳入的NioServerSocketChannel的class對象
回到channelFactory(new ReflectiveChannelFactory<C>(channelClass))方法, 點進去, 咱們看到:
public B channelFactory(io.netty.channel.ChannelFactory<? extends C> channelFactory) { return channelFactory((ChannelFactory<C>) channelFactory); }
繼續跟:
public B channelFactory(io.netty.channel.ChannelFactory<? extends C> channelFactory) { return channelFactory((ChannelFactory<C>) channelFactory); }
跟到最後:
public B channelFactory(ChannelFactory<? extends C> channelFactory) { this.channelFactory = channelFactory; return (B) this; }
這裏初始化了channelFactory, 而這個channelFactory就是剛纔建立的ReflectiveChannelFactory對象, 這裏咱們記住這個對象中初始化了咱們的NioServerSocket的class對象
至此, 咱們的ServerSocketChannel的class對象初始化完成
咱們跟到最開始的第五步, 初始化客戶端Handler:
.childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) { ch.pipeline().addLast(new StringDecoder()); ch.pipeline().addLast(new StringEncoder()); ch.pipeline().addLast(new ServerHandler()); } });
childHandler()方法比看起來比較複雜, 其實不難理解, 就是傳入ChannelInitializer類子類的一個對象(有關匿名內部類不知道的同窗能夠找下相關資料學習下), 也就是一個Handler, 這個Handler是作什麼的, 目前不須要關心, 之後會講到, 這裏咱們只需知道這個方法傳入一個handler對象
咱們點進childHandler這個方法:
public ServerBootstrap childHandler(ChannelHandler childHandler) { this.childHandler = childHandler; return this; }
發現一樣很是簡單的初始化了handler屬性
這一小節至此結束, 只是初始化了ServerBootstrap的各個屬性, 是否是很是簡單
咱們能夠看到, 經過對象build的方式, 能夠初始化很是多的屬性, 而且代碼要比構造方法的方式可讀性要好的多, 同窗們能夠將這種思想用在本身的代碼當中...