官网: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](https://img-blog.csdnimg.cn/img_convert/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](https://img-blog.csdnimg.cn/img_convert/ac6854e66f687197fb7ba35319d0e4ea.png)
初始化过程
所以,createExtension返回的实例就是 qosProtocolWrapper,所以服务暴露(export)或者调用的时候(ref)顺序就是
qosProtocolWrapper -> protocolFilterWrapper -> protocolListenerWraper -> dubboProtocol ,以此来实现类AOP的功能。