1. 程式人生 > >第四章 dubbo內核之aop源碼解析

第四章 dubbo內核之aop源碼解析

講解 bool protoc ext height adapt 成對 spa logs

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源碼解析