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的更多相关文章
随机推荐
- Codeforces - 24D 有后效性的DP处理
题意:在n*m的网格中,某个物体初始置于点(x,y),每一步行动都会等概率地停留在原地/往左/往右/往下走,求走到最后一行的的步数的数学期望,其中n,m<1000 lyd告诉我们这种题目要倒推处 ...
- js定时器执行
第一种:问题请求代表执行打印出来的是什么? //定时器执行页面崩溃 var bo = true; setTimeout(function () { console.log("定时器执行&qu ...
- Ubuntu18.04安装thunderbird并设置中文
Ubuntu18.04安装thunderbird并设置中文 安装thunderbird sudo apt-get install thunderbird 安装中文包 sudo apt-get inst ...
- lua-nginx-module模块常用命令
ngx.location.capture 用法: local res = ngx.location.capture(uri, options) 发起一个同步非阻塞的nginx子请求,uri是inter ...
- IO概念解析------同步异步阻塞非阻塞
各个IO Model的比较如图所示: 阻塞和非阻塞强调的是程序在等待调用结果(消息,返回值)时的状态. 阻塞调用是指调用结果返回之前,当前线程会被挂起.调用线程只有在得到结果之后才会返回.非阻塞调用 ...
- C语言中结构体定义
struct test { int a; }; /* 定义一个结构体,名字是test,这样就可以使用struct test 来定义变量.比如 struct test a; */ typedef str ...
- Ubuntu 16.04安装IntelliJ出品的数据库管理工具DataGrip
IntelliJ出品的东西有一个共同特定,就是代码提示做的非常好. DataGrip是除了MySQL Workbench之外的另一个选择. 一.下载 https://www.jetbrains.com ...
- (转)Linux:使用libgen.h:basename,dirname
Linux:使用libgen.h:basename,dirname basename以及dirname是两个命令: [test1280@localhost ~]$ which basename /bi ...
- [Git & GitHub] 利用Git Bash进行第一次提交文件
转载:https://blog.csdn.net/dietime1943/article/details/72420042 利用Git Bash进行第一次提交文件 快下班的时候,MD群里有人问怎么向g ...
- extern、 const、static的理解
1.extern:是一个声明,用来告诉编译器其它文件中存在这个变量,可以拿到使用.是文件级的 2.static: 是一个文件内的声明,只能在本文件内使用,是文件中的(函数级的) 3.const ...