注:分析的Dubbo版本是2.5.7。java
圖1 ReferenceConfig.get()的時序圖spring
ReferenceConfig的時序圖如圖1所示,咱們來看下ProxyFactory的實現類,以下圖2所示。ide
圖2 ProxyFactory的實現類ui
來看下JdkProxyFactory的getProxy(Invoker<T>)實現,以下所示。this
public <T> T getProxy(Invoker<T> invoker) throws RpcException { Class<?>[] interfaces = null; String config = invoker.getUrl().getParameter("interfaces"); if (config != null && config.length() > 0) { String[] types = Constants.COMMA_SPLIT_PATTERN.split(config); if (types != null && types.length > 0) { interfaces = new Class<?>[types.length + 2]; interfaces[0] = invoker.getInterface(); interfaces[1] = EchoService.class; for (int i = 0; i < types.length; i++) { interfaces[i + 1] = ReflectUtils.forName(types[i]); } } } if (interfaces == null) { interfaces = new Class<?>[]{invoker.getInterface(), EchoService.class}; } return getProxy(invoker, interfaces); }
getProxy(Invoker<T>,Class<?>)返回一個JDK動態代理,以下所示。spa
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) { return (T) Proxy.newProxyInstance( Thread.currentThread().getContextClassLoader(), interfaces, new InvokerInvocationHandler(invoker)); }
往深處走,咱們要作的就是去分析InvokerInocationHandler的實現。.net
接下來,咱們來看下ReferenceConfig在哪被使用到。使用ReferenceConfig的有ReferenceBean和ReferenceAnnotationBeanPostProcessor,下面咱們只分析ReferenceBean。我猜想ReferenceAnnotationBeanPostProcessor有多是用於註解的方式,不過目前我沒有去驗證過,只是猜想而已,SpringAop就是經過BeanPostProcessor來實現的。代理
ReferenceBean繼承了ReferenceConfig,實現了FactoryBean。若是熟悉Spring中FactoryBean的做用,讀到此處,應該對ReferenceBean要幹什麼有點眉目了。code
圖3 ReferenceBean繼承了ReferenceConfigxml
ReferenceBean的getObject方法,返回ReferenceCofig的get()結果,源碼以下。
@Override public Object getObject() throws Exception { return get(); }
由此我能夠猜想,Dubbo的consumer端,將要調用的provider提供的接口interface,經過FactoryBean轉換爲JDK動態代理,然後在JDK動態代理裏面封裝了實現細節。這種方式我在Mybatis-spring中見過。
由ReferenceBean看出,Dubbo的contributor們仍是很熟悉Spring的。
在DubboNamespaceHandler中註冊了ReferenceBean,以下圖所示。不理解NamespaceHandler的同窗能夠先去了解下Spring的NamespaceHandler,DubboNamespaceHandler用於解析Dubbo自定義的Spring標籤。
圖4 DubboNamespaceHandler中用到了ReferenceBean
DubboNamespaceHandler的源碼以下,parse(Element,ParserContext)返回的是個RootBeanDefinition ,這個beanDefinition的beanClass正是ReferenceBean。爲何須要個RootBeanDefinition,由於Spring中每一個定義的bean都會掃描爲一個BeanDefinition,不理解的同窗能夠先去看下Spring IOC的實現。
public class DubboBeanDefinitionParser implements BeanDefinitionParser { private static final Logger logger = LoggerFactory.getLogger(DubboBeanDefinitionParser.class); private static final Pattern GROUP_AND_VERION = Pattern.compile("^[\\-.0-9_a-zA-Z]+(\\:[\\-.0-9_a-zA-Z]+)?$"); private final Class<?> beanClass; private final boolean required; public DubboBeanDefinitionParser(Class<?> beanClass, boolean required) { this.beanClass = beanClass; this.required = required; } @Override public BeanDefinition parse(Element element, ParserContext parserContext) { return parse(element, parserContext, beanClass, required); } @SuppressWarnings("unchecked") private static BeanDefinition parse(Element element, ParserContext parserContext, Class<?> beanClass, boolean required) { RootBeanDefinition beanDefinition = new RootBeanDefinition(); beanDefinition.setBeanClass(beanClass); beanDefinition.setLazyInit(false); ...... return beanDefinition; } }
以下圖5所示,Spring掃描到<dubbo:reference ...>的時候,就會調用DubboNamespaceHandler來解析。
圖5 consumer(消費者)端定義的xml