bootStrap家族介绍----1AbstractBootStrap介绍

本章主要介绍AbstractBootStrap 以及BootStrap,ServerBootStrap  主要运用了建造者模式(bootStrap的构造)以及门面模式(不需要注意细节,屏蔽了)

 

 

 

 

 

一:AbstractBootStrap解析:

 

 

 

AbstratBootStrap:channel的工厂setteer方法

public B channelFactory(ChannelFactory<? extends C> channelFactory) { //默认的channelfactory的构造方法

if (channelFactory == null) {

throw new NullPointerException("channelFactory");

} else if (this.channelFactory != null) {

throw new IllegalStateException("channelFactory set already");

} else {

this.channelFactory = channelFactory;

return this.self();

}

}

 

 

public B channel(Class<? extends C> channelClass) {

    if (channelClass == null) {

        throw new NullPointerException("channelClass");

    } else {

        return this.channelFactory((io.netty.channel.ChannelFactory)(new ReflectiveChannelFactory(channelClass)));

    }

}

 

 

public interface ChannelFactory<T extends Channel> extends io.netty.bootstrap.ChannelFactory<T> {

T newChannel();

}

 

 

ReflectiveChannelFactory  class类:

public class ReflectiveChannelFactory<T extends Channel> implements ChannelFacory<T>{

 

public ReflectiveChannelFactory(Class<? extends T> clazz) {

if (clazz == null) {

throw new NullPointerException("clazz");

} else {

this.clazz = clazz;

}

}

 

public T newChannel() {

try {

return (Channel)this.clazz.getConstructor().newInstance();// 用于反射调用无参构造方法创建一个Chanel

} catch (Throwable var2) {

throw new ChannelException("Unable to create Channel from class " + this.clazz, var2);

}

}

 

}

 

 

AbstratBootStrap:bind方法:(只有bind而没有connect是因为在serverbootstrap中,会调用abstractBootStrap构造函数,将bossgroup作为group进行bind操作): 用于绑定前述工厂创建的Channel到本地的一个端口

public ChannelFuture bind() {

    this.validate();//检验数据的有效性

    SocketAddress localAddress = this.localAddress;

    if (localAddress == null) {

        throw new IllegalStateException("localAddress not set");

    } else {

        return this.doBind(localAddress);//调用dobind()进行监听服务

    }

}

 

 

public B validate() {//判断group以及channelFactory是否初始化,是否为null

if (this.group == null) {

throw new IllegalStateException("group not set");

} else if (this.channelFactory == null) {

throw new IllegalStateException("channel or channelFactory not set");

} else {

return this.self();

}

}

 

 

 

 

AbstratBootStrap:doBind(final SocketAddress localAddress)方法:

Netty的特点是 事件驱动 doBind()的注册和绑定就是两个异步事件,注册是将Channel注册到Reactor线程池,绑定是指Channel获取到了本地的一个TCP端口。

所以Netty源码里大量采用了ChannelFuture。当一个事件完成时,会回调注册到channelfuture上的ChannelFutureListener方法,从而实现异步操作。

Netty4为了简化逻辑处理逻辑,遵循这样一条规则:一个Channel产生的IO事件始终由其注册到的线程处理,可知注册和绑定事件都将在同一个线程也就是Channel注册到的线程执行。

private ChannelFuture doBind(final SocketAddress localAddress) {

    final ChannelFuture regFuture = this.initAndRegister();//创建Channel并注册到线程池

    final Channel channel = regFuture.channel();

    if (regFuture.cause() != null) {//注册失败

        return regFuture;

    } else if (regFuture.isDone()) {//Channel注册完成并且成功

        ChannelPromise promise = channel.newPromise();

        doBind0(regFuture, channel, localAddress, promise);

        return promise;

    } else {//注册是异步事件,有可能此时还未注册完成,可采用异步操作(添加一个监听事件)

        final AbstractBootstrap.PendingRegistrationPromise promise = new AbstractBootstrap.PendingRegistrationPromise(channel);

        regFuture.addListener(new ChannelFutureListener() {

            //该方法会在注册完成时进行调用

            public void operationComplete(ChannelFuture future) throws Exception {

                Throwable cause = future.cause();

                if (cause != null) {

                //注册过程时有异常 就失败

                    promise.setFailure(cause);

                } else {

                     //注册完成并成功

                    promise.registered();//设置为注册到的线程(源代码返回true?啥意思)

                    AbstractBootstrap.doBind0(regFuture, channel, localAddress, promise);

                }

 

            }

        });

        return promise;

    }

}

 

 

 

 

initAndRegister()方法主要分为3个部分:

  • 创建Channel

  • 绑定用户自定义的Handler()

  • 将该Channel注册到Reactor中去

 

 

//在后面会用一个专门的章节进行解析

 

final ChannelFuture initAndRegister() {

    Channel channel = null;

 

    try {

        channel = this.channelFactory.newChannel();//创建一个Channel(看后面的Channel的初始化)

        this.init(channel);//初始化Handler(),由子类bootstrap或者serverBootStrap进行实现,可视为一个模板方法

    } catch (Throwable var3) {

        if (channel != null) {

            channel.unsafe().closeForcibly();

            return (new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE)).setFailure(var3);

        }

       //还没有注册到线程池。使用默认线程GlobalEventExecutor

        return (new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE)).setFailure(var3);

    }

    // 将channel注册到Reactor线程池

    ChannelFuture regFuture = this.config().group().register(channel);

    if (regFuture.cause() != null) {

        if (channel.isRegistered()) {

            channel.close();

        } else {

            channel.unsafe().closeForcibly();

        }

    }

 

    return regFuture;

}

 

 

 

 

 

initAndRegister之后,就进行doBind0()操作; 

 

private static void doBind0(final ChannelFuture regFuture, final Channel channel, final SocketAddress localAddress, final ChannelPromise promise) {

channel.eventLoop().execute(new Runnable() {

public void run() {

if (regFuture.isSuccess()) {

channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);

} else {

promise.setFailure(regFuture.cause());

}

 

}

});

}

 

这个bind过程夹杂很多私货,总结一下流程:

  1. 使用ChannelFactory创建一个Channel

  2. 调用init()方法初始化Channel,主要是绑定处理器

  3. 注册到一个Reactor线程池

  4. 对注册的异步结果处理:注册成功进行绑定操作,此时绑定失败将会关闭Channel返回异步绑定失败,绑定成功返回异步成功;注册失败直接返回异步注册失败。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值