官网: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有很多实现类,如下:
默认的协议使用的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<Class<?>> 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增强的实现,通过代码我们可以看到:循环把一个实例当作另一个类的构造参数,然后实例化后注入,具体过程如下:
所以,createExtension返回的实例就是 qosProtocolWrapper,所以服务暴露(export)或者调用的时候(ref)顺序就是
qosProtocolWrapper -> protocolFilterWrapper -> protocolListenerWraper -> dubboProtocol ,以此来实现类AOP的功能。