ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);
final Protocol dubboProtocol = loader.getExtension("dubbo");
final Protocol adaptiveExtension = loader.getAdaptiveExtension();

第一行代码在2.2 dubbo-spi源码解析中讲过,本节来看第二行代码。

一、获取一个ExtensionLoader

第一行代码后获得的loader:

  • Class<?> type = interface com.alibaba.dubbo.rpc.Protocol
  • ExtensionFactory objectFactory = AdaptiveExtensionFactory(适配类)
    • factories = [SpringExtensionFactory实例, SpiExtensionFactory实例]

二、getExtension("dubbo")

调用层级:

 ExtensionLoader<T>.getExtension()
--createExtension(String name)
----getExtensionClasses().get(name)//获取扩展类
------loadExtensionClasses()
--------loadFile(Map<String, Class<?>> extensionClasses, String dir)
----injectExtension(instance);//ioc
----wrapper包装;//aop

createExtension(String name),该方法源码如下:

     private T createExtension(String name) {
/** 从cachedClasses缓存中获取所有的实现类map,之后通过name获取到对应的实现类的Class对象 */
Class<?> clazz = getExtensionClasses().get(name);
if (clazz == null) {
throw findException(name);
}
try {
/** 从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);
15 Set<Class<?>> wrapperClasses = cachedWrapperClasses;
16 if (wrapperClasses != null && wrapperClasses.size() > 0) {
17 for (Class<?> wrapperClass : wrapperClasses) {
18 instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
19 }
20 }
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的单参构造器,符合这样条件的会被列入AOP增强类。放置在loader的私有属性cachedWrapperClasses中。

此时的loader:

  • Class<?> type = interface com.alibaba.dubbo.rpc.Protocol
  • ExtensionFactory objectFactory = AdaptiveExtensionFactory(适配类)
    • factories = [SpringExtensionFactory实例, SpiExtensionFactory实例]
  • cachedWrapperClasses = [class ProtocolListenerWrapper, class ProtocolFilterWrapper]

再来看createExtension(String name)中的红色部分,就是今天的重点AOP。如上所讲,我在cachedWrapperClasses中缓存了两个AOP增强类:class ProtocolListenerWrapper和class ProtocolFilterWrapper。

首先是获取ProtocolListenerWrapper的单参构造器,然后创建ProtocolListenerWrapper实例,最后完成对ProtocolListenerWrapper实例进行属性注入,注意此时的instance=ProtocolListenerWrapper实例,而不再是之前的DubboProtocol实例了。之后使用ProtocolFilterWrapper以同样的方式进行包装,只是此时ProtocolFilterWrapper包装的是ProtocolListenerWrapper实例,也就是类似于这样的关系:

 instance = ProtocolFilterWrapper实例 {
protocol = ProtocolListenerWrapper实例 {
protocol = DubboProtocol实例
}
}

来看一下ProtocolListenerWrapper源码:

 package com.alibaba.dubbo.rpc.protocol;

 import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
import com.alibaba.dubbo.rpc.Exporter;
import com.alibaba.dubbo.rpc.ExporterListener;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.InvokerListener;
import com.alibaba.dubbo.rpc.Protocol;
import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.dubbo.rpc.listener.ListenerExporterWrapper;
import com.alibaba.dubbo.rpc.listener.ListenerInvokerWrapper; import java.util.Collections; 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源码如下:

 package com.alibaba.dubbo.rpc.protocol;

 import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
import com.alibaba.dubbo.rpc.Exporter;
import com.alibaba.dubbo.rpc.Filter;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Protocol;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcException; import java.util.List; 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实例。

至此,aop结束。

第四章 dubbo内核之aop源码解析的更多相关文章

  1. 第三章 dubbo内核之ioc源码解析

    dubbo的IOC具体实现在:T injectExtension(T instance)方法中.该方法只在三个地方被使用: createAdaptiveExtension() --injectExte ...

  2. 老生常谈系列之Aop--Spring Aop源码解析(二)

    老生常谈系列之Aop--Spring Aop源码解析(二) 前言 上一篇文章老生常谈系列之Aop--Spring Aop源码解析(一)已经介绍完Spring Aop获取advice切面增强方法的逻辑, ...

  3. 老生常谈系列之Aop--Spring Aop源码解析(一)

    老生常谈系列之Aop--Spring Aop源码解析(一) 前言 上一篇文章老生常谈系列之Aop--Spring Aop原理浅析大概阐述了动态代理的相关知识,并且最后的图给了一个Spring Aop实 ...

  4. AOP源码解析:AspectJAwareAdvisorAutoProxyCreator类的介绍

    AspectJAwareAdvisorAutoProxyCreator 的类图 上图中一些 类/接口 的介绍: AspectJAwareAdvisorAutoProxyCreator : 公开了Asp ...

  5. AOP源码解析之二-创建AOP代理前传,获取AOP信息

    AOP源码解析之二-创建AOP代理前传,获取AOP信息. 上篇文章对AOP的基本概念说清楚了,那么接下来的AOP还剩下两个大的步骤获取定义的AOP信息,生成代理对象扔到beanFactory中. 本篇 ...

  6. Spring系列(五):Spring AOP源码解析

    一.@EnableAspectJAutoProxy注解 在主配置类中添加@EnableAspectJAutoProxy注解,开启aop支持,那么@EnableAspectJAutoProxy到底做了什 ...

  7. 【Spring源码分析】AOP源码解析(上篇)

    前言 前面写了六篇文章详细地分析了Spring Bean加载流程,这部分完了之后就要进入一个比较困难的部分了,就是AOP的实现原理分析.为了探究AOP实现原理,首先定义几个类,一个Dao接口: pub ...

  8. Spring AOP源码解析——专治你不会看源码的坏毛病!

    昨天有个大牛说我啰嗦,眼光比较细碎,看不到重点.太他爷爷的有道理了!要说看人品,还是女孩子强一些. 原来记得看到一个男孩子的抱怨,说怎么两人刚刚开始在一起,女孩子在心里就已经和他过完了一辈子.哥哥们, ...

  9. dubbo系列四、dubbo服务暴露过程源码解析

    一.代码准备 1.示例代码 参考dubbo系列二.dubbo+zookeeper+dubboadmin分布式服务框架搭建(windows平台) 2.简单了解下spring自定义标签 https://w ...

随机推荐

  1. java json和对象互相装换

    java json和对象互相装换 1.com.alibaba.fastjson.JSON 2.com.fasterxml.jackson.databind.ObjectMapper

  2. 移动端二三事【三】:transform的矩阵(matrix)操作、transform操作函数及注意事项

    *每当在DOM浏览器中增加动态效果时,使用强大的transform和transition,总是很酸爽.抛开css,使用js操作transform还真的有点复杂,涉及到线性代数中的矩阵,但是js操作又不 ...

  3. CSS3利用背景渐变和background-size配合完成渐变与条纹效果[持续更新中...]

    1.不等垂直条纹. <!-- 不等垂直条纹 --> <div class="div1"></div>div1 div{ width: 200px ...

  4. 【python学习-3】python数据类型

    1.数字 在python 2.x中,数字类型有4种,int.long.float 和 complex(复数):而python 3 中,只有 int.float 和 complex 3种,python ...

  5. Android View事件分发-从源码分析

    View事件分发-从源码分析 学习自 <Android开发艺术探索> https://blog.csdn.net/qian520ao/article/details/78555397?lo ...

  6. gson 生成json有\u003d异常字符处理

    只需将Gson的初始化修改为 Gson gson = new GsonBuilder().disableHtmlEscaping().create(); 连接 http://blog.csdn.net ...

  7. [CQOI2009]跳舞

    思路:二分答案+最大流.二分答案$m$,表示最多跳$m$轮.将每个人拆成两个点$a_i$$b_i$,$a_i$表示与任何人跳舞,$b_i$表示与不喜欢的人跳舞.对于第$i$个人,连一条从$a_i$到$ ...

  8. notepad++ 如何选择10000行-20000行之间的文本?

    最近要上传导入一批数据,但是数据太多,一次上传不了,所以就要分批上传,而且数据全部在一个txt里面,这时就想一次复制一部分出来导入,直到导入完成,但是问题来了,数据太多,选择1到10000行,鼠标要拉 ...

  9. 阿里云esc云服务器IP不能访问的解决办法

    问题:阿里云服务器,专有网络,web设置完毕,在服务器中localhost能够访问,并且关闭防火墙,但是使用公网ip无法访问. 解决:找到本实例安全组,配置规则,按照要求填入80或其他端口.配置完成后 ...

  10. ASP.NET MVC异步验证是如何工作的02,异步验证表单元素的创建

    在上一篇"ASP.NET MVC异步验证是如何工作的01,jQuery的验证方式.错误信息提示.validate方法的背后"中,了解了jQuery如何验证,如何显示错误信息,本篇要 ...