Dubbo源码解析之服务引用

注:分析的Dubbo版本是2.5.7。java

1.ReferenceConfig的时序图

                  

                                                     图1 ReferenceConfig.get()的时序图spring

2.ProxyFactory的实现类

    ReferenceConfig的时序图如图1所示,咱们来看下ProxyFactory的实现类,以下图2所示。ide

                 

                                                           图2 ProxyFactory的实现类ui

3.JdkProxyFactory的实现分析

    来看下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来实现的。代理

4.ReferenceBean使用了ReferenceConfig

    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的。    

5.ReferenceBean在哪被使用到

    在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

相关文章
相关标签/搜索