Dubbo2.7.3版本源码学习系列三: Dubbo注解版本加载配置原理

前言

一、Dubbo配置类

  • 根据RPC原理,服务提供者得找一个地方存储服务信息,服务消费者得从某个地方消费服务。按照这样的逻辑,我们还要了解下Dubbo注解版本的一些基本配置是如何加载的。根据官网提供的dubbo-demo-annotation-provider模块中的Application.java文件。我们可以看到有一个静态内部类,而它内部维护了一个叫registryConfig的bean。根据官网的如下信息: 在这里插入图片描述以及上篇博客提到的@EnableDubboConfig注解的作用,它就是根据是否在dubbo.properties配置相关的配置然后去实例化相关的配置bean,若我们所有的配置都以java config的方式来配置的话,那这个注解基本上没啥用了,因为这个注解导入的DubboConfigBindingRegistrar和DubboConfigBindingsRegistrar扩展器中,会从配置文件中读取当前要实例化bean的配置前缀对应的配置信息,若读取的配置为空,则取消当前bean的配置,具体代码如下:

    // prefix的值就是分别为: dubbo.application、dubbo.registry等等
    Map<String, Object> properties = getSubProperties(environment.getPropertySources(), prefix);
    
    if (CollectionUtils.isEmpty(properties)) {
        if (log.isDebugEnabled()) {
            log.debug("There is no property for binding to dubbo config class [" + configClass.getName()
                    + "] within prefix [" + prefix + "]");
        }
        return;
    }	
    

    然后我们大胆猜测,当我们配置dubbo.application.name时,在Dubbo一定有一个叫ApplicationConfig的类来存储当前应用的名称(就像spring的spring.application.name一样)。于是我们修改ProviderConfiguration类为如下内容:

    	@Configuration
        @EnableDubbo(scanBasePackages = "org.apache.dubbo.demo.provider")
        @PropertySource("classpath:/spring/dubbo-provider.properties")
        static class ProviderConfiguration {
            @Bean
            public RegistryConfig registryConfig() {
                RegistryConfig registryConfig = new RegistryConfig();
                registryConfig.setAddress("zookeeper://192.168.111.146:2181");
                return registryConfig;
            }
    
            @Bean
            public ApplicationConfig applicationConfig() {
                ApplicationConfig applicationConfig = new ApplicationConfig();
                applicationConfig.setName("dubbo-demo-annotation-provider-from-ProviderConfiguration");
                return applicationConfig;
            }
        }	
    

    并重启服务提供者类,查看控制台输出的日志,可以发现注册在zookeeper中的服务对应的应用名也进行了修改。

    	[06/04/20 13:37:17:015 CST] main  INFO config.AbstractConfig:  [DUBBO] Export dubbo service org.apache.dubbo.demo.DemoService to local registry url : 
    	injvm://127.0.0.1/org.apache.dubbo.demo.DemoService?anyhost=true&application=dubbo-demo-annotation-provider-from-ProviderConfiguration&bean.name=ServiceBean:org.apache.dubbo.demo.DemoService&bind.ip=真实ip地址&bind.port=20880&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=org.apache.dubbo.demo.DemoService&methods=sayHello&pid=17180&register=true&release=&side=provider&timestamp=1586151436848, dubbo version: , current host: 真实ip地址
    

    既然,Dubbo每个配置类对应的是一个bean,那这个bean会不会实现spring的各种扩展呢?于是我们对如下类挨个进行检查:
    在这里插入图片描述
    纳尼,只有ConfigCenterBean稍微有点扩展,它实现了ApplicationContextAware, DisposableBean, EnvironmentAware三个接口,讲道理,这三个接口跟操作spring环境对象有关,压根不能影响加载配置的流程。看来配置类并没有什么扩展逻辑。同样的,在上篇博客介绍**@EnableDubboConfig注解时,有提到DubboConfigBindingBeanPostProcessor, 它是一个专门管理Dubbo配置的一个后置处理器,它一共实现了BeanPostProcessor, InitializingBean两个接口。(好家伙,偷偷的注册,还有这么多功能,看我怎么把你识破). 看到这两个接口应该能明白这个后置处理器要做什么事了,它会首先调用InitializingBeanafterPropertiesSet然后再调用BeanPostProcessor**的postProcessBeforeInitialization, 然后再调用postProcessAfterInitialization。(还好我记得pring bean初始化流程,哈哈)

二、DubboConfigBindingBeanPostProcessor的afterPropertiesSet方法

  • 源码如下:
    @Override
    public void afterPropertiesSet() throws Exception {
    	// 先从spring中去获取DubboConfigBinder类型的bean,若spring中
    	// 没有维护,则自己手动创建默认的配置绑定器: DefaultDubboConfigBinder
    	// 并绑定至当前对象中
        initDubboConfigBinder();
    	// 从spring bean中拿到@EnableDubboConfigBinding注解导入的
    	// 自定义配置bean: NamePropertyDefaultValueDubboConfigBeanCustomizer
        initConfigBeanCustomizers();
    
    }
    
  • 所以大致可以了解,此方法就是初始化当前bean内部的一些属性(其实我很好奇为什么不让spring来自动装配它。。。),方便为后面的Dubbo配置提供条件

三、DubboConfigBindingBeanPostProcessor的postProcessBeforeInitialization方法

  • 源码如下:
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    
    	// 它只对内部维护的beanName感兴趣,此beanName叫org.apache.dubbo.config.ProtocolConfig#0
    	// 看了下DubboConfigBindingBeanPostProcessor对beanName的处理,发现只有构造方法有赋值。因为是在DubboConfigBindingRegistrar.java中设置了构造方法的参数, 指定了让spring使用哪个构造器进行实例化对象
        if (beanName.equals(this.beanName) && bean instanceof AbstractConfig) {
    
            AbstractConfig dubboConfig = (AbstractConfig) bean;
    
            bind(prefix, dubboConfig);
    
            customize(beanName, dubboConfig);
    
        }
    
        return bean;
    }
    
  • 此方法的具体作用就是将传入bean(ProtocolConfig)绑定配置,因为创建出来的dubbo配置bean里面内部的属性是空的,此方法执行完后,protocolConfig里面的属性就被填充了(会从JVM系统配置、当前系统配置环境、classpath中的properties文件中去取值)。
  • 至此,Dubbo将默认的配置类的属性填充了。但要注意,不是所有的dubbo配置类都会走上面的流程。在上篇博客中有提到,当没有手动添加dubbo配置类给spring的话eg: 如下:
        @Bean
        public RegistryConfig registryConfig() {
            RegistryConfig registryConfig = new RegistryConfig();
            registryConfig.setAddress("zookeeper://192.168.111.146:2181");
            return registryConfig;
        }
    

,dubbo会添加默认的配置类的bean。

四、总结

  • 综上所述: 若没有手动的配置Dubbo内置的一些bean的话,会统一交给DubboConfigBindingRegistrar去注册,通过DubboConfigBindingRegistrar注册有个特点,每个配置bean(eg: ProtocolConfig)会对应一个DubboConfigBindingBeanPostProcessor, 并通过它来获取所有的配置文件JVM系统配置、当前系统配置环境、classpath中的properties去取配置,并填充bean中的属性
  • 注意: 官网中提供了配置的加载流程: http://dubbo.apache.org/zh-cn/docs/user/configuration/configuration-load-process.html, 但是就目前源码来看并没有看到从注册中心去配置的流程,以后再继续完善此部分的文档。
  • I am a slow walker, but I never walk backwards.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值