概述
Dubbo中也支持Spring AOP类似功能,通过装饰者模式,使用包装类包装原始的扩展点实例。在扩展点实现前后插入其他逻辑,实现AOP功能。说这很绕口啊,那什么是包装类呢?举个例子你就知道了
class A{
private A a;
public A(A a){
this.a = a;
}
public void do(){
// 插入扩展逻辑
a.do();
}
}
这里的插入扩展逻辑,是不是就是实现了AOP功能呢?比如说Protocol类,有2个Wrapper,分别是ProtocolFilterWrapper和ProtocolListenerWrapper,我们可以在dubbo-rpc/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol看到:
filter=com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper
listener=com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper
我们在最开始的Dubbo SPI的例子中,我们打个断点就很明显了,得到的myProtocol对象其实是这样的:
如果你调用export方法的话,会先经历ProtocolFilterWrapper的export方法,再经历ProtocolListenerWrapper的export方法,这样就实现了Spring AOP的功能
源码解析
aop 的实现是通过createExtension方法 实现
private T createExtension(String name) {
// 1.加载配置文件所有拓展类,得到配置名-拓展类的map,从map中获取到拓展类
Class<?> clazz = getExtensionClasses().get(name);
if (clazz == null) {
throw findException(name);
}
try {
T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
// 2.通过反射创建实例
// EXTENSION_INSTANCES这个map是配置名-拓展类实例的map
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
// 3.注入依赖,即IOC
injectExtension(instance);
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (CollectionUtils.isNotEmpty(wrapperClasses)) {
// 4.循环创建Wrapper实例
for (Class<?> wrapperClass : wrapperClasses) {
// 通过反射创建Wrapper实例
// 向Wrapper实例注入依赖,最后赋值给instance
// 自动包装实现类似aop功能
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
return instance;
} catch (Throwable t) {
throw new IllegalStateException("Extension instance (name: " + name + ", class: " +
type + ") couldn't be instantiated: " + t.getMessage(), t);
}
}
注意:
在循环创建Wrapper实例 实现的就是Wrapper实例按照加载的顺序嵌套实例化,这样能实现以下的对象:
当调用protocol 里头的方法时候,会一层层嵌套调用 实现aop效果!
注入依赖
ioc 的实现是通过injectExtension方法 实现