05_dubbo_aop
【对这行代码进行源码分析】
ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);
final Protocol dubboProtocol = loader.getExtension("dubbo"); //要分析的源码
final Protocol adaptiveExtension = loader.getAdaptiveExtension();
【对上面第二行代码进行源码分析】
先看下第一行代码执行后的ExtensionLoader实例化的结果

其中
* type =interface com.alibaba.dubbo.rpc.Protocol
* ExtensionFactory objectFactory = AdaptiveExtensionFactory(适配类)
* AdaptiveExtensionFactory成员变量factories = [ SpringExtensionFactory实例,SpiExtensionFactory实例 ]
【 getExtension(String name)调用流程 】
ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);
final Protocol dubboProtocol = loader.getExtension("dubbo");
--createExtension(name);
----getExtensionClasses() //获取扩展类
------loadExtensionClasses()
--------loadFile(Map<String, Class<?>> extensionClasses, String dir)
//ioc属性注入
----injectExtension(instance);
//aop+ioc属性注入 aop获得一个wrapper装饰类
----instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
【 createExtension(String name)源码 】
private T createExtension(String name) {
/**
* 从Holder<Map<String, Class<?>>>cachedClasses缓存中获取所有的实现类map,
* 然后通过name获取到对应的实现类(此时只是一个对象实例,还没有属性注入)
*/
Class<?> clazz = getExtensionClasses().get(name);
if (clazz == null) {
throw findException(name);
}
try {
/**
* 从 ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES 类缓存中获取到对应的实现类的Class对象,
* 如果没有,直接创建,之后放入缓存
*/
T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
injectExtension(instance);
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (wrapperClasses != null && wrapperClasses.size() > 0) {
for (Class<?> wrapperClass : wrapperClasses) {
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
return instance;
} catch (Throwable t) {
throw new IllegalStateException("Extension instance(name: " + name + ", class: " +
type + ") could not be instantiated: " + t.getMessage(), t);
}
}
回头看下META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol文件内容
registry=com.alibaba.dubbo.registry.integration.RegistryProtocol
dubbo=com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol
filter=com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper
listener=com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper
mock=com.alibaba.dubbo.rpc.support.MockProtocol
injvm=com.alibaba.dubbo.rpc.protocol.injvm.InjvmProtocol
rmi=com.alibaba.dubbo.rpc.protocol.rmi.RmiProtocol
hessian=com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocol
com.alibaba.dubbo.rpc.protocol.http.HttpProtocol
com.alibaba.dubbo.rpc.protocol.webservice.WebServiceProtocol
thrift=com.alibaba.dubbo.rpc.protocol.thrift.ThriftProtocol
memcached=com.alibaba.dubbo.rpc.protocol.memcached.MemcachedProtocol redis=com.alibaba.dubbo.rpc.protocol.redis.RedisProtocol
com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper和com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper,这两个类不含有@Adaptive注解且含有Protocol的单参数构造方法,符合这2个条件的类会被列入AOP增强类,会被防止在ExtensionLoader的实例缓存Set<Class<?>> cachedWrapperClasses;中。

此时的loader:
* type =interface com.alibaba.dubbo.rpc.Protocol
* ExtensionFactory objectFactory = AdaptiveExtensionFactory(适配类)
* AdaptiveExtensionFactory成员变量factories = [ SpringExtensionFactory实例,SpiExtensionFactory实例 ]
* cachedWrapperClasses = [ class ProtocolListenerWrapper, class ProtocolFilterWrapper ]


再来看createExtension(String name )中的aop红色部分代码,即dubbo的aop部分。
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (wrapperClasses != null && wrapperClasses.size() > 0) {
for (Class<?> wrapperClass : wrapperClasses) {
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
在cachedWrapperClasses中缓存两个AOP增强类:ProtocolListenerWrapper和ProtocolFilterWrapper。
首先获取ProtocolListenerWrapper的单参数构造方法,然后创建ProtocolWrapper实例,最后完成对ProtocolListenerWrapper实例的属性注入,注意此时的instance = ProtocolListenerWrapper实例,而不是之前的DubboProtocol实例,之后使用ProtocolFilterWrapper以同样的方式进行包装,只是此时的ProtocolFilterWrapper包装的是ProtocolListenerWrapper实例。
instance = ProtocolFilterWrapper实例{
protocol = ProtocolListenerWrapper实例{
protocol = DubboProtocol实例
}
}
【 ProtocolListenerWrapper源码 】
/**
* ListenerProtocol
*
* @author william.liangf
*/
public class ProtocolListenerWrapper implements Protocol { private final Protocol protocol; public ProtocolListenerWrapper(Protocol protocol) {
if (protocol == null) {
throw new IllegalArgumentException("protocol == null");
}
this.protocol = protocol;
} public int getDefaultPort() {
return protocol.getDefaultPort();
} public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
return protocol.export(invoker);
}
return new ListenerExporterWrapper<T>(protocol.export(invoker),
Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(ExporterListener.class)
.getActivateExtension(invoker.getUrl(), Constants.EXPORTER_LISTENER_KEY)));
} public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
return protocol.refer(type, url);
}
return new ListenerInvokerWrapper<T>(protocol.refer(type, url),
Collections.unmodifiableList(
ExtensionLoader.getExtensionLoader(InvokerListener.class)
.getActivateExtension(url, Constants.INVOKER_LISTENER_KEY)));
} public void destroy() {
protocol.destroy();
} }
【 ProtocolFilterWrapper源码 】
/**
* ListenerProtocol
*
* @author william.liangf
*/
public class ProtocolFilterWrapper implements Protocol { private final Protocol protocol; public ProtocolFilterWrapper(Protocol protocol) {
if (protocol == null) {
throw new IllegalArgumentException("protocol == null");
}
this.protocol = protocol;
} private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
Invoker<T> last = invoker;
List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
if (filters.size() > 0) {
for (int i = filters.size() - 1; i >= 0; i--) {
final Filter filter = filters.get(i);
final Invoker<T> next = last;
last = new Invoker<T>() { public Class<T> getInterface() {
return invoker.getInterface();
} public URL getUrl() {
return invoker.getUrl();
} public boolean isAvailable() {
return invoker.isAvailable();
} public Result invoke(Invocation invocation) throws RpcException {
return filter.invoke(next, invocation);
} public void destroy() {
invoker.destroy();
} @Override
public String toString() {
return invoker.toString();
}
};
}
}
return last;
} public int getDefaultPort() {
return protocol.getDefaultPort();
} public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
return protocol.export(invoker);
}
return protocol.export(buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER));
} public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
return protocol.refer(type, url);
}
return buildInvokerChain(protocol.refer(type, url), Constants.REFERENCE_FILTER_KEY, Constants.CONSUMER);
} public void destroy() {
protocol.destroy();
} }
【结果】
最后返回的instance是ProtocolFilterWrapper对象,
final Protocol dubboProtocol = loader.getExtension("dubbo");
这句代码最后的dubboProtocol是ProtocolFilterWrapper实例。
【参考文章】
https://www.cnblogs.com/java-zhao/p/7478136.html
05_dubbo_aop的更多相关文章
随机推荐
- FPGA基础学习(6) -- 原语
目录 1. IBUF和IBUFDS(IO) 2. IDDR(Input/Output Functions) 3. IBUFG和IBUFGDS(IO) 原语,即primitive.不同的厂商,原语不同: ...
- vue.js学习笔记(一)——vue-cli项目的目录结构
vue.js是一套构建用户界面的渐进式框架.vue采用自底向上增量开发的设计.vue的核心库只关心视图层,非常容易学习,非常容易与其它库和已有项目整合.vue完全有能力驱动采用单文件组件和vue生态系 ...
- 通过遍历类向Aspose.cell模板中插入数据
/// <summary> /// 遍历类所有字段 /// </summary> /// <param name="designer">aspo ...
- EXCEL 使用宏 打水印
Sub 宏1() ' ' 宏1 宏 //用于调整列宽 加边框 ' ' 快捷键: Ctrl+w ' ActiveCell.Cells.Select ActiveCell.Cells.EntireColu ...
- $bzoj1025-SCOI2009$游戏 群论 $dp$
题面描述 \(windy\)学会了一种游戏.对于\(1\)到\(N\)这\(N\)个数字,都有唯一且不同的1到N的数字与之对应.最开始\(windy\)把数字按顺序\(1,2,3,\cdot ...
- Notepad++配置替换快捷配置
我们经常会收到实施或客户提供的excel文档,需要将对应的数据从数据库删除,那么我们怎么能快速把excel中的内容加上单引号和逗号到数据库中处理呢,我们可以使用nodepad++中的替换功能. 1.打 ...
- 使用AChartEngine画动态曲线图
AChartEngine是一个开源的Android图表库,可以用来画折线图.平滑折线图.饼图.直方图等等.使用简单,功能强大. AChartEngine官网:http://www.achartengi ...
- redux-thunk, redux-logger 阮一峰 ( react中间件 )
http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_two_async_operations.html Redux 入门教程(二):中 ...
- EntityManager对象管理
根据EntityManager对象的管理方式,可以有以下两种类型: — 容器托管的(container-managed)EntityManager对象 容器托管的EntityManager对象最简单, ...
- Shiro与Spring、Springmvc的整合
1.在web.xml中配置Shiro的filter 在web系统中,shiro也通过filter进行拦截.filter拦截后将操作权交给spring中配置的filterChain(过虑链儿) shir ...