【Netty】(4)—原始碼AbstractBootstrap

piny發表於2021-09-09

一、概念

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做一個小小的鋪墊吧。
以上原始碼只是個人的理解,如有不對希望能夠留言指點。萬分感謝!

原文出處:https://www.cnblogs.com/qdhxhz/p/10092919.html  

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3034/viewspace-2818941/,如需轉載,請註明出處,否則將追究法律責任。

相關文章