• 适配器模式


     适配器模式

    适配器模式是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。

    适配器模式一般用于屏蔽业务逻辑与第三方服务的交互,或者是新老接口之间的差异。

    在Dubbo中,所有的数据都是通过Netty来负责传输的,然后这就涉及了消息编解码的问题。

    所以,首先它有一个编解码器的接口,负责编码和解码。

    1. @SPI
    2. public interface Codec2 {
    3. @Adaptive({Constants.CODEC_KEY})
    4. void encode(Channel channel, ChannelBuffer buffer, Object message) throws IOException;
    5. @Adaptive({Constants.CODEC_KEY})
    6. Object decode(Channel channel, ChannelBuffer buffer) throws IOException;
    7. enum DecodeResult {
    8. NEED_MORE_INPUT, SKIP_SOME_INPUT
    9. }
    10. }

    然后,有几个实现类,比如DubboCountCodec、DubboCodec、ExchangeCodec等。

    但是,当打开这些类的时候,就会发现,他们都是Dubbo中普通的类,只是实现了Codec2接口,其实不能直接作用于Netty编解码。

    这是因为,Netty编解码需要实现ChannelHandler接口,这样才会被声明成Netty的处理组件。比如像MessageToByteEncoder、ByteToMessageDecoder那样。

    鉴于此,Dubbo搞了一个适配器,专门来适配编解码器接口。

    1. final public class NettyCodecAdapter {
    2. private final ChannelHandler encoder = new InternalEncoder();
    3. private final ChannelHandler decoder = new InternalDecoder();
    4. private final Codec2 codec;
    5. private final URL url;
    6. private final org.apache.dubbo.remoting.ChannelHandler handler;
    7. public NettyCodecAdapter(Codec2 codec, URL url, org.apache.dubbo.remoting.ChannelHandler handler) {
    8. this.codec = codec;
    9. this.url = url;
    10. this.handler = handler;
    11. }
    12. public ChannelHandler getEncoder() {
    13. return encoder;
    14. }
    15. public ChannelHandler getDecoder() {
    16. return decoder;
    17. }
    18. private class InternalEncoder extends MessageToByteEncoder {
    19. @Override
    20. protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
    21. org.apache.dubbo.remoting.buffer.ChannelBuffer buffer = new NettyBackedChannelBuffer(out);
    22. Channel ch = ctx.channel();
    23. NettyChannel channel = NettyChannel.getOrAddChannel(ch, url, handler);
    24. codec.encode(channel, buffer, msg);
    25. }
    26. }
    27. private class InternalDecoder extends ByteToMessageDecoder {
    28. @Override
    29. protected void decode(ChannelHandlerContext ctx, ByteBuf input, List<Object> out) throws Exception {
    30. ChannelBuffer message = new NettyBackedChannelBuffer(input);
    31. NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel(), url, handler);
    32. //解码对象
    33. codec.decode(channel, message);
    34. //省略部分代码...
    35. }
    36. }
    37. }

    上面的代码中,可以看到,NettyCodecAdapter类适配的是Codec2接口,通过构造函数传递实现类,然后定义了内部的编码器实现和解码器实现,同时它们都是ChannelHandler。

    这样的话,在内部类里面的编码和解码逻辑,真正调用的还是Codec2接口。

    最后再来看看,该适配器的调用方式。

    1. //通过SPI方式获取编解码器的实现类,比如这里是DubboCountCodec
    2. Codec2 codec = ExtensionLoader.getExtensionLoader(Codec2.class).getExtension("dubbo");
    3. URL url = new URL("dubbo", "localhost", 22226);
    4. //创建适配器
    5. NettyCodecAdapter adapter = new NettyCodecAdapter(codec, url, NettyClient.this);
    6. //向ChannelPipeline中添加编解码处理器
    7. ch.pipeline()
    8. .addLast("decoder", adapter.getDecoder())
    9. .addLast("encoder", adapter.getEncoder())

    以上,就是Dubbo中关于编解码器对于适配器模式的应用。

  • 相关阅读:
    第十章:聊聊ThreadLocal
    阿里云 —— Windows下“阿里云音视频通信RTC“ 之 云端录制编译C++的SDK接口
    【数字图像处理笔记】01-数字图像基础
    Apache Airflow (十一) :HiveOperator及调度HQL
    春秋云境靶场CVE-2022-30887漏洞复现(任意文件上传漏洞)
    6-Mysql子查询,多表连接(内连接,外连接,交叉连接)
    有没有一段代码,让你为人类的智慧所折服
    TMS320F28374S之CMPSS
    原生php 实现redis登录五次被禁,隔天再登陆
    “数字驱动 智领未来”—传化化学项目启动会
  • 原文地址:https://blog.csdn.net/s178435865/article/details/138009873