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的更多相关文章
随机推荐
- thinkpadT480安装archlinux
制作U盘启动盘 下载archlinux镜像 下载powerison 将镜像刻录到U盘中 设置bios 如果已经安装了win8+系统, 开机重启然后按f1,进入设置界面,加载启动项中将usb放到最前 保 ...
- [BZOJ 1937][Shoi2004]Mst 最小生成树
传送门 $ \color{red} {solution:} $ 对于每条树边\(i\),其边权只可能变小,对于非树边\(j\),其边权只可能变大,所以对于任意非树边覆盖的树边有 \(wi - di & ...
- 用selenium工具做软件自动化测试的面试题及答案
1.selenium中如何判断元素是否存在? 答:isElementPresent 2.selenium中hidden或者是display = none的元素是否可以定位到? 答:不可以定位到 3.s ...
- QueryRunner(DBUtils) 结果集实例
转自:http://www.cnblogs.com/myit/p/4272824.html# 单行数据处理:ScalarHandler ArrayHandler MapHandler ...
- C++程序设计
C++程序设计 之前学过C++课程,但是时间有点久,忘了很多,这里做一个简单的回顾. 网站推荐: C++在线编译器 学习C++之前,您可以先了解C语言. c++的扩展名一般为cpp(cplusplus ...
- JAVA学习3:Eclipse中集成Tomcat
问题: 很多时候在Eclipse中启动Tmocat后,不能访问本机的localhost:8080主页,并且其他项目也不能访问. 原因: 打开Tomcat下的webapp后也找补到项目目录,这是因为Ec ...
- table定位
Table定位 在 web 页面中经常会遇到 table 表格,特别是后台操作页面比较常见.本篇详细讲解 table 表格如何定位. 1.1 table特性 1.table 页面查看源码一般有这几个明 ...
- Python数据类型(字典)
文章内容参考了教程:http://www.runoob.com/python/python-basic-syntax.html#commentform Python 字典(Dictionary) 字典 ...
- ADT安装Genymotion的eclipse插件安装及错误解决办法
接触安卓开发也有很长一段时间了,但是一直使用的真机测试程序,因为感觉android模拟器实在是太不方便,运行慢,而且经常出错.最近听人介绍说Genymotion这款Android模拟器相当不错,于是打 ...
- jquery 部分函数源码解析
JSON.stringify源码(在看extend文档的时候看到) var object1 = { apple: 0, banana: {weight: 52, price: 100}, cherry ...