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

相關文章
相關標籤/搜索