aop实现原理_Dubbo SPI中AOP实现原理

官网:http://dubbo.apache.org/zh-cn/docs/2.7/source_code_guide/dubbo-spi/

从官网说明中我们可以看到,dubbo spi是java spi的一种增强实现,也就是这种spi机制确保了dubbo高扩展的能力。

说明

dubbo spi增强的实现中包含了ioc和aop的实现,本篇主要讲解aop的实现原理。

  • ioc即依赖注入,dubbo spi中可以注入普通的类和spring bean
  • aop即面向切面编程,用过spring的应该都知道

实现原理

包装类(Wrap类)

public class A implements I {    private I i;    public A(I i) {        this.i = i;    }}

上面这种类就是Wrap 类,即父类是自己的成员变量,把父类当作构造函数的参数传进来。

Dubbo中一些Wrap类如下:

public class QosProtocolWrapper implements Protocol {    private Protocol protocol;    public QosProtocolWrapper(Protocol protocol) {         this.protocol = protocol;    }}
public class ProtocolListenerWrapper implements Protocol {    private Protocol protocol;    public ProtocolListenerWrapper(Protocol protocol) {         this.protocol = protocol;    }}

扩展点自动包装

我们知道dubbo spi的机制是运行期间寻找具体的实现类,Protocol有很多实现类,如下:

ec5949230af959b364dc48bc1af3b844.png

扩展点实现

默认的协议使用的dubbo

@SPI("dubbo")public interface Protocol {

那么运行期间根据URL获取Protocol实例时默认就是DubboProtocol

ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();

但是真正获取的可能不是DubboProtocol,而且增强后的包装类,从源码中我们来分析:

 private T createExtension(String name, boolean wrap) {        // 1. getExtensionClasses()加载所有的实现类        Class> clazz = getExtensionClasses().get(name);        if (clazz == null) {            throw findException(name);        }        try {            T instance = (T) EXTENSION_INSTANCES.get(clazz);            if (instance == null) {                EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());                instance = (T) EXTENSION_INSTANCES.get(clazz);            }            // 2. 依赖注入            injectExtension(instance);            if (wrap) {                // 3.包装类排序                List> wrapperClassesList = new ArrayList<>();                if (cachedWrapperClasses != null) {                    wrapperClassesList.addAll(cachedWrapperClasses);                    wrapperClassesList.sort(WrapperComparator.COMPARATOR);                    Collections.reverse(wrapperClassesList);                }                // 4. AOP实现                if (CollectionUtils.isNotEmpty(wrapperClassesList)) {                    for (Class> wrapperClass : wrapperClassesList) {                        Wrapper wrapper = wrapperClass.getAnnotation(Wrapper.class);                        if (wrapper == null                                || (ArrayUtils.contains(wrapper.matches(), name) && !ArrayUtils.contains(wrapper.mismatches(), name))) {                            instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));                        }                    }                }            }            initExtension(instance);            return instance;        } catch (Throwable t) {            throw new IllegalStateException("Extension instance (name: " + name + ", class: " +                    type + ") couldn't be instantiated: " + t.getMessage(), t);        }    }

1.获取所有的实现类

ExtensionLoader初始化的时候会从多个地方获取实现类,然后缓存起来

  • META-INF/dubbo/internal/
  • META-INF/dubbo/
  • META-INF/services/

其中loadClass的时候会找到Wrap Class,然后缓存到cachedWrapperClasses

2.依赖注入

注入依赖的实例

3.包装类排序

sort by sort desc

4.AOP实现

这一步就是AOP增强的实现,通过代码我们可以看到:循环把一个实例当作另一个类的构造参数,然后实例化后注入,具体过程如下:

ac6854e66f687197fb7ba35319d0e4ea.png

初始化过程

所以,createExtension返回的实例就是 qosProtocolWrapper,所以服务暴露(export)或者调用的时候(ref)顺序就是

qosProtocolWrapper -> protocolFilterWrapper -> protocolListenerWraper -> dubboProtocol ,以此来实现类AOP的功能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值