注:分析的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