Bootstrap 源码分析

Netty 源码分析: Bootstrap

1. 结构

先看一个这个类的类层次结构,

好,这个结构还是比较明晰的,然后看他的主要字段,因为这些字段比较重要,在后面的代码分析中是用的上的。

// options 选项
private final Map<ChannelOption<?>, Object> childOptions = new LinkedHashMap<ChannelOption<?>, Object>();
// 属性
private final Map<AttributeKey<?>, Object> childAttrs = new LinkedHashMap<AttributeKey<?>, Object>();
// worker 线程池,为啥没有 boss ? 待会说
private volatile EventLoopGroup childGroup;
// handler
private volatile ChannelHandler childHandler;

   可以看到很多参数就是在我们进行 bootstrap 配置的时候进行设置的。但是我们注意到我们一般配置线程池的时候是有一个 boss 一个 worker ,但是这里只有一个引用是怎么回事?接着我们看一下构造方法。有一行注释 “ Specify the {@link EventLoopGroup} which is used for the parent (acceptor) and the child (client).” 这个意思就是说这里把线程池分为了 parent 和 child ,其中 parent 就是我们说的 boss 他的作用就是用来接收请求的连接,然后 worker 线程池就是用来处理读写事件的。最后我们找到两个参数的构造方法,用来初始化这两个参数,这里明显的能看到原来 boss 是在父类中定义的。所以调用父类的构造方法初始化了。过程和这个里对 Worker 初始化一样,做了检测,就不贴代码了。

public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
        // 初始化 boss
        super.group(parentGroup);
        if (childGroup == null) {
            throw new NullPointerException("childGroup");
        }
        if (this.childGroup != null) {
            throw new IllegalStateException("childGroup set already");
        }
        // 初始化 worker
        this.childGroup = childGroup;
        return this;
    }

2. 常用方法分析

   好的,上面看到了 bootstrap 里面的属性,接着分析一下我们常用的方法,主要就是 groupoptionhandlerchildHandlerbindconnect

1. option

   逻辑比较简单,如果 value 为 null 就说明要删除这个 option ,否则就放到表里面。

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 (B) this;
    }

2. handler/childHandler

   这个是直接设置了引用,就把 handler 设置为传入的参数。childHandler 同理。

public B handler(ChannelHandler handler) {
        if (handler == null) {
            throw new NullPointerException("handler");
        }
        this.handler = handler;
        return (B) this;
    }

3. channel

   这里面直接调用了 channelFactory ,也就是在 3.x 中设置 channel 工厂,这里做了进一步的封装。这个 channel 工厂的作用就是利用反射 newInstance 。

4. bind

   好吧,这个可能是现在遇到的最麻烦的一个方法了,因为如果要说的话,里面牵扯的东西太多了,又再次引入的了新的类和方法。不着急先了解大概的思路,再看源码。

   在 bind 方法中写出来只有几行代码,但是每一个方法里面涉及的东西就比较多。首先是进行了验证,验证就是检测线程池 和 channelFactory 是不是正常被赋值了。接着就是重要的 doBind 方法。

   doBind 分为两个重要操作,第一个就是:对 channel 进行初始化和注册操作,然后把执行绑定操作。也就是这里涉及到的两个重要的方法: initAndRegisterdoBind0

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏博岩Java大讲堂

多线程--同步与锁

25330
来自专栏DOTNET

asp.net web api 异常捕获

1 向客户端发送错误消息 使用throw new HttpResponseException()向客户端抛出错误信息。 HttpResponseExceptio...

532120
来自专栏xingoo, 一个梦想做发明家的程序员

堆 栈-相关知识

一、预备知识—程序的内存分配 一个由c/C++编译的程序占用的内存分为以下几个部分 1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量...

20280
来自专栏Spark学习技巧

JAVA之ClassLoader

JAVA基础系列之ClassLoader 一,Java类的加载、链接与初始化 1,加载:查找并加载类的二进制数据 • 通过一个类的全限定名来获取定义此类的二进制...

22690
来自专栏www.96php.cn

【thinkphp】3.2二维数组模糊查询

我们在做数据列表的时候 把文章列表数据缓存到缓存里 取出来大概的结构是这样的 Array (     [0] => Array         (       ...

36490
来自专栏coderhuo

可怕的extern关键字一、不利之处二、例子三、分析四、正确做法

如果函数原型改变的话,每个extern声明的地方都要改一遍。 如果有地方没改到呢? 我们通过一个例子来看下悲剧是怎么发生的。

10020
来自专栏python爬虫日记

转载、Python的编码处理(二)

然后,大多数人的做法是,调用encode/decode进行调试,并没有明确思考为何出现乱码

10320
来自专栏奔跑的蛙牛技术博客

什么是字节码?

字节码(Byte-code)是一种包含执行程序,由一序列 op 代码/数据对组成的二进制文件,是一种中间码。字节是电脑里的数据量单位。

50230
来自专栏北京马哥教育

搞定Linux Shell文本处理工具,看完这篇集锦就够了

Linux Shell是一种基本功,由于怪异的语法加之较差的可读性,通常被Python等脚本代替。既然是基本功,那就需要掌握,毕竟学习Shell脚本的过程中,还...

37730
来自专栏哲学驱动设计

模式应用:自定义匹配

    本篇博客记录了我在工作过程中的一个设计单元。 需求 GIX4项目中需要为非国标清单进行匹配,用户自定义匹配规则。规则可以被存储到数据库中,下次重复使用...

20950

扫码关注云+社区

领取腾讯云代金券