dubbo源码分析-consumer端1-consumer代理生成

本文深入分析了Dubbo消费者端的代理生成过程。从ReferenceBean的初始化,到通过FactoryBean实例化对象,再到Protocol的adaptive extension和ClusterInvoker的创建。最后,通过JavassistProxyFactory生成代理类并使用InvokerInvocationHandler处理接口调用。整个过程详细解释了Dubbo如何实现透明化的服务调用。
摘要由CSDN通过智能技术生成

        dubbo(官网地址)是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,是阿里巴巴SOA服务化治理方案的核心框架。目前,阿里巴巴内部已经不再使用dubbo,但对很对未到一定量级的公司来说,dubbo依然是一个很好的选择。

        之前在使用duubo的时候,对dubbo有了一些初步的了解,但没有深入,有些问题还是不清楚。所以准备静下心来看下dubbo源码。这里假设你对dubbo有一定的了解,不再详细的讲解dubbo的架构。如果没接触过dubbo,可以先从其官网了解。

      dubbo号称通过spring的方式可以透明化接入应用,对应用没有任何api侵入。下面看看官方的consumer demo,其配置如下:

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
	http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

        <dubbo:reference id="demoService" interface="com.alibaba.dubbo.demo.DemoService" /> 

	<bean class="com.alibaba.dubbo.demo.consumer.DemoAction" init-method="start">
		<property name="demoService" ref="demoService" />
	</bean>

</beans>
       另外还提供了一份properties文件:

dubbo.container=log4j,spring
dubbo.application.name=demo-consumer
dubbo.application.owner=
dubbo.registry.address=multicast://224.5.6.7:1234
     应用中的调用:
package com.alibaba.dubbo.demo.consumer;

import com.alibaba.dubbo.demo.DemoService;

public class DemoAction {
    
    private DemoService demoService;

    public void setDemoService(DemoService demoService) {
        this.demoService = demoService;
    }

<pre name="code" class="java">    public void start() throws Exception {    
        String hello = demoService.sayHello("who are you");
        System.out.println(hello);
    }
}

         可以看到,代码方面确实是零侵入,而在配置方面,则是增加了一些服务的声明,环境配置之类的(不可缺少)。对于开发者来说非常友好。那么dubbo是如何做到这点的呢。 这个demoService在consumer端明明没有具体的实现,为何能够正常的调用并获取到结果? 要了解原因,必须先了解spring开发的一个接口:FactoryBean。 

        spring中有两种bean,一种是普通的bean,一种是工厂bean,即FactoryBean。普通bean通过class字符串代表的类直接实例化对象,而工厂bean则是通过class字符串代表的工厂类的getObject()方法来实例化对象。如以下FactoryBean在spring中返回的是MyObject对象,而不是MyFactoryBean对象。 这里不过多介绍FactoryBean,有兴趣的同学可以自行google。

class MyFactoryBean implements FactoryBean<Object> {
    public Object getObject() throws Exception {
        return new MyObject();
    }
    
    ........
}
        了解了FactoryBean后,仍然有困惑。在上面的配置里,并没有出现FactoryBean的实现类。这里需要了解另外一个spring的知识点:schema扩展。在dubbo中,所有namespace=dubbo的标签将被dubbo自己解析, 具体见com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler。其中reference对应的类为com.alibaba.dubbo.config.spring.ReferenceBean,ReferenceBean是一个FactoryBean,通过getObject()来产生代理类,我们的故事也是从此类开始。

        ReferenceBean继承自ReferenceConfig,并实现了FactoryBean, ApplicationContextAware, InitializingBean, DisposableBean。

        由于实现了InitializingBean,在初始化各个属性后会调用afterPropertiesSet, 实现比较简单,主要是对没有初始化的几个属性尝试用公共的默认配置进行初始化,这里就不再细讲:

    public void afterPropertiesSet() throws Exception {
        if (getConsumer() == null) {
            // 如果没有配置consumer属性,则使用默认的consumer属性
        }
        if (getApplication() == null
                && (getConsumer() == null || getConsumer().getApplication() == null)) {
            // 如果没有配置application则使用默认的application
        }
        if (getModule() == null
                && (getConsumer() == null || getConsumer().getModule() == null)) {
            // 如果没有配置module则使用默认的module
        }
        if ((getRegistries() == null || getRegistries().size() == 0)
                && (getConsumer() == null || getConsumer().getRegistries() == null || getConsumer().getRegistries().size() == 0)
                && (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().size() == 0)) {
            // 如果没有配置registries则使用默认的registries
        }
        if (getMonitor() == null
                && (getConsumer() == null || getConsumer().getMonitor() == null)
                && (getApplication() == null || getApplication().getMonitor() == null)) {
            // 如果没有配置monitor则使用默认monitor
        }
        // 如果设置了init属性且为true,则初始化对象,默认是不初始化的
        Boolean b = isInit();
        if (b == null && getConsumer() != null) {
            b = getConsumer().isInit();
        }
        if (b != null && b.booleanValue()) {
            getObject();
        }
    }
        由于实现了FactoryBean,当需要初始化或者应用中需要用到时,会调用getObject()方法获取实际的对象:

    public Object getObject() throws Exception {
        return get();
    }
        ge
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值