Netty 源码分析1.4 NioEventLoopGroup类的register方法

###################################################################################
后续文章中都会对一些代码逻辑进行说明,但原文的英文注释一般不会直译,进行保留,只会说明那些没有注释的地方
###################################################################################

本文中关联的所有文章的总目录可以参看:系列文章目录

1前言

      前面我们通过分析ServerBootstrap类的bind方法了解到,通道在注册时实际上调用的是NioEventLoopGroup.register 方法。具体的分析逻辑可以参看 Netty 源码分析一ServerBootstrap的bind方法
      而本篇我们讲解的就是ServerBootstrap类在处理bind方法时,涉及到的NioEventLoopGroup类中的register方法具体的业务操作;

2 register方法

2.1 方法序列图

在这里插入图片描述

2.2 NioEventLoopGroup register源码学习

2.2.1 方法调用的来源

      在Netty 源码分析一 NioEventLoopGroup创建逻辑 文章中我们了解了NioEventLoopGroup类的继承关系。而NioEventLoopGroup类本身实际上是没有重写register方法的,通过上面序列图我们也知道,调用NioEventLoopGroup类的register方法,实现上就是调用MultithreadEventLoopGroup类的register方法;

      而在Netty 源码分析一ServerBootstrap的bind方法 这个文章中doBind方法内部的initAndRegister 方法 这部分的分析中我们可以知道在调用NioEventLoopGroup类的register方法时传入的参数是 NioServerSocketChannel 这个对象。

      至此我们已经了解到我们为什么要分析这个方法?而分析这个方法是哪个类?哪个方法?方法的入参是什么?在此再画一个简版的流程图

调用
传入的是NioServerSocketChannel作为参数
ServerBootstrap.bind方法
AbstractBootstrap.initAndRegister
NioEventLoopGroup.register方法

2.2.2 register 方法详细分析

       通过前面已经知道,实际调用的是MultithreadEventLoopGroup类的register方法,具体代码如下所示:

@Override
    public ChannelFuture register(Channel channel) {
        // 该方法是是在AbstractBootstrap中的initAndRegister中调用的
        // channel 类传入的是NioServerSocketChannel对象
        // next()方法最终调用是的父类MultithreadEventExecutorGroup中的next()方法
        return next().register(channel);
    }
  1. next() 方法讲解
    对于MultithreadEventExecutorGroup类中的next方法代码如下所示:
@Override
    public EventExecutor next() {
        // 在NioEventLoopGroup初始化时,我们知道chooser属性赋值的是 DefaultEventExecutorChooserFactory对象
        // 而该类的内部EventExecutor 数组中放入的都是NioEventLoop对象
        // 所以这个方法返回的是 NioEventLoop实例
        return this.chooser.next();
    }

       而DefaultEventExecutorChooserFactory 方法的逻辑我们在 Netty 源码分析一 NioEventLoopGroup创建逻辑 中讲解该方法具体的逻辑,在此就不再讲解了;
       其实我们结合前面学习的NioEventLoopGroup的创建,就很容易理解上面代码实际上执行的结果了;

2.3 NioEventLoop 类

       在看NioEventLoop.register 方法前,我们先对这个类进行简单的了解下,这样才能便于知道这个类的一些执行逻辑

2.3.1 NioEventLoop 类的继承关系图

在这里插入图片描述

2.3.2 NioEventLoop初始化

       通过 Netty 源码分析一 NioEventLoopGroup创建逻辑 这篇文章中讲解,我们可以知道NioEventLoop 类是在NioEventLoopGroup类的newChild方法中创建的,具体代码如下所示:

@Override
    protected EventLoop newChild(Executor executor, Object... args) throws Exception {
        EventLoopTaskQueueFactory queueFactory = args.length == 4 ? (EventLoopTaskQueueFactory) args[3] : null;
        return new NioEventLoop(this, executor, (SelectorProvider) args[0],
            ((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2], queueFactory);
    }

初始化NioEventLoop 这个类时,它通过args这个参数列表来设置中间的三个参数:
SelectorProvider 取args[0]
SelectStrategyFactory 取args[1]
RejectedExecutionHandler 取args[2]

而这些值的来源,我们先通过调用链路来看下:
在这里插入图片描述
       通过上面可以看出,它是在图形中标出的第2的它个类方法时,开始传入这个可变个数的参数Object…
而这个类中的参数是由上面图形中标出1的这个类和方法传入的,如此我们看下NioEventLoopGroup的这个方法的具体代码:

public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider,
                             final SelectStrategyFactory selectStrategyFactory) {
        // 可以看出父类是从第3个参数开始都是由Object.... args这个参数来接受了
        super(nThreads, executor, selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject());
    }

       通过上面的代码,我们可以知道args[2] 这个参数是 RejectedExecutionHandlers.reject() 来生成的
而args[0]、args[1]我们还是只看到了具体的对象,没有看到这些对象实际的赋值情况,所以我们需要看下调用上面方法的方法传入的,也就是下面这个方法:

public NioEventLoopGroup(
            int nThreads, Executor executor, final SelectorProvider selectorProvider) {
        this(nThreads, executor, selectorProvider, DefaultSelectStrategyFactory.INSTANCE);
    }

       而通过上面的方法情况可以看出,args[1] 传入的是 DefaultSelectStrategyFactory.INSTANCE 这个实例,实际上就是DefaultSelectStrategyFactory这个对象

那args[0] 这个参数我们需要继续看上面的类构建方法情况:

public NioEventLoopGroup(int nThreads, Executor executor) {
        this(nThreads, executor, SelectorProvider.provider());
    }

       所以调用的是jdk中的SelectorProvider.provider()方法来创建的,因为我的机子是windows系统,所以最后创建出来的是WindowsSelectorProvider这个类的对象;

       通过上面分析我们知道,在NioEventLoopGroup类的newChild方法的args这个参数的个数只有三个,所以传入NioEventLoop的值是null

最终我们知道了NioEventLoop类初始时传入的具体参数情况了:

类名属性类型属性名赋值
AbstractEventExecutorEventExecutorGroupparentNioEventLoopGroup对象
SingleThreadEventExecutorExecutorexecutorThreadPerTaskExecutor对象
SingleThreadEventExecutorRejectedExecutionHandlerrejectedExecutionHandlerRejectedExecutionHandler对象
NioEventLoopSelectorProviderselectorProviderWindowsSelectorProvider对象
NioEventLoopEventLoopTaskQueueFactoryqueueFactoryPlatformDependent.newMpscQueue() 对象,在类中初始化的
NioEventLoopSelectorunwrappedSelectorWindowsSelectorProvider.openSelector()创建返回
NioEventLoopSelectorselectorWindowsSelectorProvider.openSelector()创建返回
NioEventLoopSelectStrategyselectStrategyDefaultSelectStrategyFactory对象

2.3.3 NioEventLoop register方法

       通过前面的分析我们已经了解了,最终register方法调用的是NioEventLoop的register方法,然后前面的流程图就可以做以下延伸了:

调用
传入的是NioServerSocketChannel作为参数
按规律获取一个NioEventLoop调用
ServerBootstrap.bind方法
AbstractBootstrap.initAndRegister
NioEventLoopGroup.register方法
NioEventLoop.register

      通过本篇的最前面的register序列图中,和实际的代码中,我们知道因为NioEventLoop 没有重写registe,是在其父类SingleThreadEventLoop中实现的,我们看这个方法的具体实现:

@Override
    public ChannelFuture register(Channel channel) {
        // channel 就是由NioEventLoopGroup.register方法传入的
        // NioEventLoopGroup.register里面的channel是在AbstractBootstrap里面的initAndRegister 方法中创建出来的NioServerSocketChannel对象
        return register(new DefaultChannelPromise(channel, this));
    }

这代码没有什么好说的,具体的传入参数的路径我们通过前面几篇文章和本篇前面讲的,就是代码中注释中说明的。最后代码又调用到下面重载的方法中:

@Override
    public ChannelFuture register(final ChannelPromise promise) {
        ObjectUtil.checkNotNull(promise, "promise");
        // promise.channel() 实际上是NioServerSocketChannel这个对象
        // NioServerSocketChannel 这个对象的unsafe方法创建出来的对象中的register
        promise.channel().unsafe().register(this, promise);
        return promise;
    }

自此,我们相当于将NioEventLoop里面的register方法已经讲解完了。

而在最后的方法中实际上调用的是NioServerSocketChannel 这个类,而这个类具体的业务是什么样的?创建时各个属性的赋值情况如何?我们在下一篇NioServerSocketChannel中进行讲解

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值