【netty】IO模式切换以及背后的思想

netty时如何切换IO模式的

在学习netty时,会发现netty切换IO模式的方式非常便捷。
如下列代码,基于NIO的模式通过netty构架一个服务端。

EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel channel) throws Exception {
                            channel.pipeline()
                                    .addLast(new DemoHandler); 
                        }
                    })
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);

如果哪天我们想切换IO模式,想从NIO修改为BIO,仅仅只需要修改两个地方。

  1. 将NioEventLoopGroup -> OioEventLoopGroup
  2. 将NioServerSocketChannel修改为OioServerSocketChannel
EventLoopGroup bossGroup = new OioEventLoopGroup();
        EventLoopGroup workerGroup = new OioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup).channel(OioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel channel) throws Exception {
                            channel.pipeline()
                                    .addLast(new DemoHandler); 
                        }
                    })
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);

其他代码不变,底层的IO模式就轻松切换了。通常在jdk上开发,我们写业务逻辑,从BIO切换到NIO,这两种IO模式的编程风格的不同,让我们在切换时很难下手。netty封装了这种复杂性,提供了简易的API,那时怎么做到的呢。

IO模式切换的设计模式(泛型+反射+工厂模式)

bootstrap.channel(XxxServerSocketChannel.class)这行代码意思是指定产生Channel的ChannelFactory。
bootstrap是如何根据传入class动态的生成ChannelFactory的(传入OIO,要初始化OIO的ChannelFactory,传入NIO要生成NIO的ChannelFactory)。
这里看下channel的代码逻辑:

public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> {

	public B channel(Class<? extends C> channelClass) {
        if (channelClass == null) {
            throw new NullPointerException("channelClass");
        }
        return channelFactory(new ReflectiveChannelFactory<C>(channelClass));
    }
}

这段代码需要关注两个泛型,以及一个类ReflectiveChannelFactory。

AbstractBootstrap在定义的时候用到两个泛型,B代表着的是AbstractBootstrap的子类,是父类在自己的代码范围内,获取到子类class的一种手段。C代表着的时Channel的实际类型,在子类定义时指定。

ReflectiveChannelFactory,如字面意思,是一个基于反射的ChannelFactory。传入的channelClass时希望channelFactory生产出来的对象类型。

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

    private final Class<? extends T> clazz;

    public ReflectiveChannelFactory(Class<? extends T> clazz) {
        if (clazz == null) {
            throw new NullPointerException("clazz");
        }
        this.clazz = clazz;
    }

    @Override
    public T newChannel() {
        try {
            return clazz.newInstance();
        } catch (Throwable t) {
            throw new ChannelException("Unable to create Channel from class " + clazz, t);
        }
    }
}

这里通过传入的class,通过反射创建一个新对象。由于前面传入了ChannelClass,可以指定返回值类型为传入的ChannelClass。

优点

需要什么类型的对象工厂,传入对象的class就行。
平时我们应用工厂模式,要产生A对象,需要定义A的工厂AFactory;要产生B对象,需要定义B的工厂BFactory。定义的对象一多,需要创建的工厂也多。
基于反射的工厂,就只需定义一个工厂就能产生想要类型的对象。

写个demo应用

public class ReflectiveFactory<T> {

    private Class<T> clazz;

    public ReflectiveFactory(Class<T> clazz) {
        this.clazz = clazz;
    }

    public T newInstance() {
        try {
            return clazz.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException("生成对象失败");
        }
    }

    @SuppressWarnings("unchecked")
    public static void main(String[] args) {
        // 生产水果
        ReflectiveFactory<Fruit> fruitFactory = (ReflectiveFactory<Fruit>) new ReflectiveFactory(Fruit.class);
        Fruit fruit = fruitFactory.newInstance();
    
        // 生成蔬菜
        ReflectiveFactory<Vegetable> vegetableFactory = (ReflectiveFactory<Vegetable>) new ReflectiveFactory(Vegetable.class);
        Vegetable vegetable = vegetableFactory.newInstance();
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值