1. 程式人生 > >【Netty】(4)—原始碼AbstractBootstrap

【Netty】(4)—原始碼AbstractBootstrap

原始碼AbstractBootstrap

一、概念

AbstractBootstrap是一個工具類,用於伺服器通道的一系列配置,繫結NioEventLoopGroup執行緒組,指定指定NIO的模式,指定子處理器,用於處理workerGroup,指定埠等。

通過類圖我們知道AbstractBootstrap類是ServerBootstrap及Bootstrap的基類。

總的來說可以總結

1、提供了一個ChannelFactory物件用來建立Channel,一個Channel會對應一個EventLoop用於IO的事件處理,在一個Channel的整個生命週期中
  只會繫結一個EventLoop,這裡可理解給Channel分配一個執行緒進行IO事件處理,結束後回收該執行緒。

2、AbstractBootstrap沒有提供EventLoop而是提供了一個EventLoopGroup,上篇部落格講過EventLoopGroup物件就是一個含有EventLoop的陣列。
   但是當一個連線到達,Netty會註冊一個Channel,然後EventLoopGroup會分配一個EventLoop繫結到這個channel。

3、不管是伺服器還是客戶端的Channel都需要繫結一個本地埠這就有了SocketAddress類的物件localAddress。

4、Channel有很多選項所有有了options物件LinkedHashMap<channeloption<?>, Object>

5、怎麼處理Channel的IO事件呢,我們新增一個事件處理器ChannelHandler物件。


二、原始碼

這裡只是部分AbstractBootstrap原始碼,具體可以通過ServerBootstrap或者Bootstrap點進去後,檢視父類。

public abstract class AbstractBootstrap<B extends io.netty.bootstrap.AbstractBootstrap<B, C>, C extends Channel> implements Cloneable {

    /**
     * 這裡的EventLoopGroup 作為服務端 Acceptor 執行緒,負責處理客戶端的請求接入
     * 作為客戶端 Connector 執行緒,負責註冊監聽連線操作位,用於判斷非同步連線結果。
     */
    volatile EventLoopGroup group;

    /**
     * 建立Channer 工廠 根據傳入的型別來建立不同的Channer 
     * 比如伺服器傳入的是:NioServerSocketChannel.class
     * 客戶端傳入:NioSocketChannel.class 。 加上這個註解代表這個已經過期有更好的替代類
     */
    @SuppressWarnings("deprecation")
    private volatile ChannelFactory<? extends C> channelFactory;

    /**
     * SocketAddress 是用來繫結一個服務埠 用的
     */
    private volatile SocketAddress localAddress;

    /**
     * ChannelOption 可以新增Channer 新增一些配置資訊
     */
    private final Map<ChannelOption<?>, Object> options = new LinkedHashMap<ChannelOption<?>, Object>();
    private final Map<AttributeKey<?>, Object> attrs = new LinkedHashMap<AttributeKey<?>, Object>();

    /**
     * ChannelHandler 是具體怎麼處理Channer 的IO事件。
     */
    private volatile ChannelHandler handler;

    /**
     * 傳入一個EventLoopGroup,不管服務端還是客戶端都會呼叫該方法
     */
    public B group(EventLoopGroup group) {
        if (group == null) {
            throw new NullPointerException("group");
        }
        if (this.group != null) {
            throw new IllegalStateException("group set already");
        }
        this.group = group;
        return self();
    }

    /**
     * 返回物件本身
     */
    @SuppressWarnings("unchecked")
    private B self() {
        return (B) this;
    }

    /**
     *設定服務端的Channel,Netty通過Channel工廠類建立不同的Channel。
     * 對於服務端傳入:Netty需要建立NioServerSocketChannel
     * 對於客戶端傳入:NioSocketChannel.class
     */
    public B channel(Class<? extends C> channelClass) {
        if (channelClass == null) {
            throw new NullPointerException("channelClass");
        }
        return channelFactory(new ReflectiveChannelFactory<C>(channelClass));
    }

    /**
     * 建立好Channel後,返回物件本身
     */
    @Deprecated
    public B channelFactory(ChannelFactory<? extends C> channelFactory) {
        if (channelFactory == null) {
            throw new NullPointerException("channelFactory");
        }
        if (this.channelFactory != null) {
            throw new IllegalStateException("channelFactory set already");
        }

        this.channelFactory = channelFactory;
        return self();
    }

    /**
     * 設定一些Channel相關引數
     */
    public <T> B option(ChannelOption<T> option, T value) {
        if (option == null) {
            throw new NullPointerException("option");
        }
        if (value == null) {
            synchronized (options) {
                options.remove(option);
            }
        } else {
            synchronized (options) {
                options.put(option, value);
            }
        }
        return self();
    }

    /**
     *  服務端方法: 繫結埠 對該埠進行監聽
     */
    public ChannelFuture bind(int inetPort) {
        return bind(new InetSocketAddress(inetPort));
    }

    /**
     * 客戶端方法: 需要傳入訪問的地址和埠
     */
    public ChannelFuture bind(String inetHost, int inetPort) {
        return bind(SocketUtils.socketAddress(inetHost, inetPort));
    }

    public ChannelFuture bind(SocketAddress localAddress) {

        if (localAddress == null) {
            throw new NullPointerException("localAddress");
        }
        //這個方法這裡省略調,具體可以看原始碼
        return doBind(localAddress);
    }

    /**
     * 設定父類的Handler,父類的handler是客戶端新接入的接連SocketChannel對應的ChannelPipeline 的handler
     */
    public B handler(ChannelHandler handler) {
        if (handler == null) {
            throw new NullPointerException("handler");
        }
        this.handler = handler;
        return self();
    }
}

這裡並沒有很深入的去了解AbstractBootstrap,寫這個就是為接下來寫ServerBootstrap及Bootstrap做一個小小的鋪墊吧。
以上原始碼只是個人的理解,如有不對希望能夠留言指點。萬分感謝!




如果一個人充滿快樂,正面的思想,那麼好的人事物就會和他共鳴,而且被他吸引過來。同樣,一個人老帶悲傷,倒黴的事情也會跟過來。
                                                      ——在自己心情低落的時候,告誡自己不要把負能量帶給別人。(大校12)