码迷,mamicode.com
首页 > 其他好文 > 详细

第四章 dubbo内核之aop源码解析

时间:2017-10-01 20:37:14      阅读:297      评论:0      收藏:0      [点我收藏+]

标签:geturl   create   title   引用   message   interface   ftp   turn   height   

1         ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);
2         final Protocol dubboProtocol = loader.getExtension("dubbo");
3         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")

调用层级:

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

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

 1     private T createExtension(String name) {
 2         /** 从cachedClasses缓存中获取所有的实现类map,之后通过name获取到对应的实现类的Class对象 */
 3         Class<?> clazz = getExtensionClasses().get(name);
 4         if (clazz == null) {
 5             throw findException(name);
 6         }
 7         try {
 8             /** 从EXTENSION_INSTANCES缓存中获取对应的实现类的Class对象,如果没有,直接创建,之后放入缓存 */
 9             T instance = (T) EXTENSION_INSTANCES.get(clazz);
10             if (instance == null) {
11                 EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
12                 instance = (T) EXTENSION_INSTANCES.get(clazz);
13             }
14             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             }
21             return instance;
22         } catch (Throwable t) {
23             throw new IllegalStateException("Extension instance(name: " + name + ", class: " + type
24                                             + ")  could not be instantiated: " + t.getMessage(),
25                 t);
26         }
27     }

这里,先给出META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol内容:

 1 registry=com.alibaba.dubbo.registry.integration.RegistryProtocol
 2 dubbo=com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol
 3 filter=com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper
 4 listener=com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper
 5 mock=com.alibaba.dubbo.rpc.support.MockProtocol
 6 injvm=com.alibaba.dubbo.rpc.protocol.injvm.InjvmProtocol
 7 rmi=com.alibaba.dubbo.rpc.protocol.rmi.RmiProtocol
 8 hessian=com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocol
 9 com.alibaba.dubbo.rpc.protocol.http.HttpProtocol
10 com.alibaba.dubbo.rpc.protocol.webservice.WebServiceProtocol
11 thrift=com.alibaba.dubbo.rpc.protocol.thrift.ThriftProtocol
12 memcached=com.alibaba.dubbo.rpc.protocol.memcached.MemcachedProtocol
13 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实例,也就是类似于这样的关系:

1 instance = ProtocolFilterWrapper实例 {
2       protocol = ProtocolListenerWrapper实例 {
3           protocol = DubboProtocol实例
4       }  
5 }    

来看一下ProtocolListenerWrapper源码:

 1 package com.alibaba.dubbo.rpc.protocol;
 2 
 3 import com.alibaba.dubbo.common.Constants;
 4 import com.alibaba.dubbo.common.URL;
 5 import com.alibaba.dubbo.common.extension.ExtensionLoader;
 6 import com.alibaba.dubbo.rpc.Exporter;
 7 import com.alibaba.dubbo.rpc.ExporterListener;
 8 import com.alibaba.dubbo.rpc.Invoker;
 9 import com.alibaba.dubbo.rpc.InvokerListener;
10 import com.alibaba.dubbo.rpc.Protocol;
11 import com.alibaba.dubbo.rpc.RpcException;
12 import com.alibaba.dubbo.rpc.listener.ListenerExporterWrapper;
13 import com.alibaba.dubbo.rpc.listener.ListenerInvokerWrapper;
14 
15 import java.util.Collections;
16 
17 public class ProtocolListenerWrapper implements Protocol {
18     private final Protocol protocol;
19 
20     public ProtocolListenerWrapper(Protocol protocol) {
21         if (protocol == null) {
22             throw new IllegalArgumentException("protocol == null");
23         }
24         this.protocol = protocol;
25     }
26 
27     public int getDefaultPort() {
28         return protocol.getDefaultPort();
29     }
30 
31     public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
32         if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
33             return protocol.export(invoker);
34         }
35         return new ListenerExporterWrapper<T>(protocol.export(invoker),
36                 Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(ExporterListener.class)
37                         .getActivateExtension(invoker.getUrl(), Constants.EXPORTER_LISTENER_KEY)));
38     }
39 
40     public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
41         if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
42             return protocol.refer(type, url);
43         }
44         return new ListenerInvokerWrapper<T>(protocol.refer(type, url),
45                 Collections.unmodifiableList(
46                         ExtensionLoader.getExtensionLoader(InvokerListener.class)
47                                 .getActivateExtension(url, Constants.INVOKER_LISTENER_KEY)));
48     }
49 
50     public void destroy() {
51         protocol.destroy();
52     }
53 }

这里的方法不做讲解,等到了服务提供者暴露服务和服务消费者引用服务的时候再做讲解。

ProtocolFilterWrapper源码如下:

 1 package com.alibaba.dubbo.rpc.protocol;
 2 
 3 import com.alibaba.dubbo.common.Constants;
 4 import com.alibaba.dubbo.common.URL;
 5 import com.alibaba.dubbo.common.extension.ExtensionLoader;
 6 import com.alibaba.dubbo.rpc.Exporter;
 7 import com.alibaba.dubbo.rpc.Filter;
 8 import com.alibaba.dubbo.rpc.Invocation;
 9 import com.alibaba.dubbo.rpc.Invoker;
10 import com.alibaba.dubbo.rpc.Protocol;
11 import com.alibaba.dubbo.rpc.Result;
12 import com.alibaba.dubbo.rpc.RpcException;
13 
14 import java.util.List;
15 
16 public class ProtocolFilterWrapper implements Protocol {
17     private final Protocol protocol;
18 
19     public ProtocolFilterWrapper(Protocol protocol) {
20         if (protocol == null) {
21             throw new IllegalArgumentException("protocol == null");
22         }
23         this.protocol = protocol;
24     }
25 
26     private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
27         Invoker<T> last = invoker;
28         List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
29         if (filters.size() > 0) {
30             for (int i = filters.size() - 1; i >= 0; i--) {
31                 final Filter filter = filters.get(i);
32                 final Invoker<T> next = last;
33                 last = new Invoker<T>() {
34 
35                     public Class<T> getInterface() {
36                         return invoker.getInterface();
37                     }
38 
39                     public URL getUrl() {
40                         return invoker.getUrl();
41                     }
42 
43                     public boolean isAvailable() {
44                         return invoker.isAvailable();
45                     }
46 
47                     public Result invoke(Invocation invocation) throws RpcException {
48                         return filter.invoke(next, invocation);
49                     }
50 
51                     public void destroy() {
52                         invoker.destroy();
53                     }
54 
55                     @Override
56                     public String toString() {
57                         return invoker.toString();
58                     }
59                 };
60             }
61         }
62         return last;
63     }
64 
65     public int getDefaultPort() {
66         return protocol.getDefaultPort();
67     }
68 
69     public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
70         if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
71             return protocol.export(invoker);
72         }
73         return protocol.export(buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER));
74     }
75 
76     public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
77         if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
78             return protocol.refer(type, url);
79         }
80         return buildInvokerChain(protocol.refer(type, url), Constants.REFERENCE_FILTER_KEY, Constants.CONSUMER);
81     }
82 
83     public void destroy() {
84         protocol.destroy();
85     }
86 }

这里的方法不做讲解,等到了服务提供者暴露服务和服务消费者引用服务的时候再做讲解。

最后返回的instance是ProtocolFilterWrapper对象,也就是说final Protocol dubboProtocol = loader.getExtension("dubbo");这句代码最后的dubboProtocol是ProtocolFilterWrapper实例。

技术分享

 

至此,aop结束。 

第四章 dubbo内核之aop源码解析

标签:geturl   create   title   引用   message   interface   ftp   turn   height   

原文地址:http://www.cnblogs.com/java-zhao/p/7478136.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!