Spring与Dubbo整合源码分析-P1

前言

根据之前的SpringBoot整合Dubbodemo可知,当编写完测试接口及其实现后,最后一步是要在启动类上加上@EnableDubbo,这样就可以启动Dubbo相关服务了,那么是如何实现的呢?

image.png

问题

SpringBoot启动类上加上@EnableDubbo这样就可以启动Dubbo相关服务了原理是什么

EnableDubbo注解解析

点开EnableDubbo注解,如下所示:

image.png

可以看到其定义中还有三个Dubbo相关的注解,分别为EnableDubboConfigDubboComponentScan和三个注解。我们知道,Java中的注解定义中如果有其他注解,那么这个注解其实就是一个复合注解,复合注解同时具备这个注解定义中的所有注解的功能(具体可以参考Java注解)。由于这部分涉及的接口太多,所以拆成两个部分来说。本章先说EnableDubboConfig注解的作用。

EnableDubboConfig

image.png

可以看到EnableDubboConfig的定义中使用了@Import注解引入了DubboConfigConfigurationRegistrar类。DubboConfigConfigurationRegistrar实现了ImportBeanDefinitionRegistrar接口,这样就可以向Spring启动时,通过registerBeanDefinitions方法向Spring容器中注册beanDefinition,如下所示:

image.png

DubboConfigConfigurationRegistrar

DubboConfigConfigurationRegistrar类中主要方法和注释如下:

public class DubboConfigConfigurationRegistrar implements ImportBeanDefinitionRegistrar, ApplicationContextAware {
  
  
  private ConfigurableApplicationContext applicationContext;
  
   /**
     * 根据导入@Configuration类的给定注释元数据,根据需要向beanDefinitionMap中添加beanDefinition
     * @param importingClassMetadata 导入类的注解元数据
     * @param registry beanDefinition注册器
     * @return void
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

      
      // 获取EnableDubboConfig注解里的键值对,这里主要获取的是multiple的值,默认为true
        AnnotationAttributes attributes = AnnotationAttributes.fromMap(
                importingClassMetadata.getAnnotationAttributes(EnableDubboConfig.class.getName()));

      
      // 获取multiple属性值
        boolean multiple = attributes.getBoolean("multiple");
      
      
      
      // ============重点===========================

      // 向Spring容器中注册DubboConfigConfiguration.Single
        registerBeans(registry, DubboConfigConfiguration.Single.class);

      // 向Spring容器中注册DubboConfigConfiguration.Multiple
        if (multiple) { // Since 2.6.6 https://github.com/apache/dubbo/issues/3193
            registerBeans(registry, DubboConfigConfiguration.Multiple.class);
        }

      // Since 2.7.6
      // 注册公共组件,5个 
      // ReferenceAnnotationBeanPostProcessor,
      // DubboConfigAliasPostProcessor,
      // DubboLifecycleComponentApplicationListener,
      // DubboBootstrapApplicationListener, 
      // DubboConfigDefaultPropertyValueBeanPostProcessor
        registerCommonBeans(registry);
    }

  
  
   @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (!(applicationContext instanceof ConfigurableApplicationContext)) {
            throw new IllegalArgumentException("The argument of ApplicationContext must be ConfigurableApplicationContext");
        }
        this.applicationContext = (ConfigurableApplicationContext) applicationContext;
    }

}

com.alibaba.spring.util.AnnotatedBeanDefinitionRegistryUtils#registerBeans方法

/**
     * 向Spring中的beanDefinitionMap注册beanDefinition
     * 
     * @param registry         {@link BeanDefinitionRegistry}
     * @param annotatedClasses {@link Annotation annotation} class
     */
    public static void registerBeans(BeanDefinitionRegistry registry, Class<?>... annotatedClasses) {

        if (ObjectUtils.isEmpty(annotatedClasses)) {
            return;
        }

        Set<Class<?>> classesToRegister = new LinkedHashSet<Class<?>>(asList(annotatedClasses));

       
        Iterator<Class<?>> iterator = classesToRegister.iterator();

        while (iterator.hasNext()) {
            Class<?> annotatedClass = iterator.next();
          // 移除已经注册过的bean,防止重复注册
            if (isPresentBean(registry, annotatedClass)) {
                iterator.remove();
            }
        }

      
      // 构建AnnotatedBeanDefinitionReader
        AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(registry);

        if (logger.isDebugEnabled()) {
            logger.debug(registry.getClass().getSimpleName() + " will register annotated classes : " + asList(annotatedClasses) + " .");
        }
        
        // 注册beanDefinition
        reader.register(classesToRegister.toArray(EMPTY_CLASS_ARRAY));

    }

org.apache.dubbo.config.spring.util.DubboBeanUtils#registerCommonBeans方法,注册公共组件

    /**
     * Register the common beans
     *
     * @param registry {@link BeanDefinitionRegistry}
     * @see ReferenceAnnotationBeanPostProcessor
     * @see DubboConfigDefaultPropertyValueBeanPostProcessor
     * @see DubboConfigAliasPostProcessor
     * @see DubboLifecycleComponentApplicationListener
     * @see DubboBootstrapApplicationListener
     */
    public static void registerCommonBeans(BeanDefinitionRegistry registry) {

        // Since 2.5.7 Register @Reference Annotation Bean Processor as an infrastructure Bean
      // 从 2.5.7版本开始注册@Reference注解的bean后置处理器作为基础组件
      registerInfrastructureBean(registry, ReferenceAnnotationBeanPostProcessor.BEAN_NAME,
                ReferenceAnnotationBeanPostProcessor.class);

        // Since 2.7.4 [Feature] https://github.com/apache/dubbo/issues/5093
        registerInfrastructureBean(registry, DubboConfigAliasPostProcessor.BEAN_NAME,
                DubboConfigAliasPostProcessor.class);

        // Since 2.7.9 Register DubboApplicationListenerRegister as an infrastructure Bean
        // https://github.com/apache/dubbo/issues/6559
        // Since 2.7.5 Register DubboLifecycleComponentApplicationListener as an infrastructure Bean
        // registerInfrastructureBean(registry, DubboLifecycleComponentApplicationListener.BEAN_NAME,
        //        DubboLifecycleComponentApplicationListener.class);

        // Since 2.7.4 Register DubboBootstrapApplicationListener as an infrastructure Bean
        // registerInfrastructureBean(registry, DubboBootstrapApplicationListener.BEAN_NAME,
        //        DubboBootstrapApplicationListener.class);
      // 从 2.7.9版本开始添加DubboApplicationListenerRegister,作为基础组件 https:github.comapachedubboissues6559
      // 从 2.7.5版本开始添加DubboLifecycleComponentApplicationListener,作为基础组件 registerInfrastructureBean(registry, DubboLifecycleComponentApplicationListener.BEAN_NAME, DubboLifecycleComponentApplicationListener.class);
      // 从 2.7.4版本开始添加DubboBootstrapApplicationListener,作为基础组件 registerInfrastructureBean(registry, DubboBootstrapApplicationListener.BEAN_NAME, DubboBootstrapApplicationListener.class);
        registerInfrastructureBean(registry, DubboApplicationListenerRegistrar.BEAN_NAME,
                DubboApplicationListenerRegistrar.class);

        // Since 2.7.6 Register DubboConfigDefaultPropertyValueBeanPostProcessor as an infrastructure Bean
      // 从 2.7.6版本开始添加DubboConfigDefaultPropertyValueBeanPostProcessor,作为基础组件 
        registerInfrastructureBean(registry, DubboConfigDefaultPropertyValueBeanPostProcessor.BEAN_NAME,
                DubboConfigDefaultPropertyValueBeanPostProcessor.class);

        // Since 2.7.15 Register DubboConfigEarlyRegistrationPostProcessor as an infrastructure Bean
      // 从 2.7.6版本开始添加DubboConfigEarlyRegistrationPostProcessor,作为基础组件
        registerInfrastructureBean(registry, DubboConfigEarlyRegistrationPostProcessor.BEAN_NAME,
                DubboConfigEarlyRegistrationPostProcessor.class);
    }

com.alibaba.spring.util.BeanRegistrar#registerInfrastructureBean方法,注册基础组件

/**
     * 向Spring容器中注册beanDefinition
     * @param beanDefinitionRegistry {@link BeanDefinitionRegistry}
     * @param beanType               the type of bean
     * @param beanName               the name of bean
     * @return if it's a first time to register, return <code>true</code>, or <code>false</code>
     */
    public static boolean registerInfrastructureBean(BeanDefinitionRegistry beanDefinitionRegistry,
                                                     String beanName,
                                                     Class<?> beanType) {

        boolean registered = false;

         // 如果beanDefinitionMap没有该bean
         // 那么就将该bean注册到beanDefinitionMap中
        if (!beanDefinitionRegistry.containsBeanDefinition(beanName)) {
          
            // 构建RootBeanDefinition
            RootBeanDefinition beanDefinition = new RootBeanDefinition(beanType);
          
            // 设置角色
            beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
          
            // 注册到beanDefinitionMp中
            beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition);
          
            registered = true;

            if (log.isInfoEnabled()) {
                log.info("The Infrastructure bean definition [" + beanDefinition
                        + "with name [" + beanName + "] has been registered.");
            }
        }

        return registered;
    }

小结一下,DubboConfigConfigurationRegistrar这个类主要是向Spring容器注册DubboConfig相关类的beanDefinition

DubboConfigConfiguration

DubboConfigConfiguration.SingleDubboConfigConfiguration.Multiple结构如下所示:

public class DubboConfigConfiguration {

    /**
     * 单个dubbo服务配置绑定
     */
    @EnableConfigurationBeanBindings({
            @EnableConfigurationBeanBinding(prefix = "dubbo.application", type = ApplicationConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.module", type = ModuleConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.registry", type = RegistryConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.protocol", type = ProtocolConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.monitor", type = MonitorConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.provider", type = ProviderConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.consumer", type = ConsumerConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.config-center", type = ConfigCenterBean.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.metadata-report", type = MetadataReportConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.metrics", type = MetricsConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.ssl", type = SslConfig.class)
    })
    public static class Single {

    }

    /**
     * 多个dubbo服务配置绑定
     */
    @EnableConfigurationBeanBindings({
            @EnableConfigurationBeanBinding(prefix = "dubbo.applications", type = ApplicationConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.modules", type = ModuleConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.registries", type = RegistryConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.protocols", type = ProtocolConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.monitors", type = MonitorConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.providers", type = ProviderConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.consumers", type = ConsumerConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.config-centers", type = ConfigCenterBean.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.metadata-reports", type = MetadataReportConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.metricses", type = MetricsConfig.class, multiple = true)
    })
    public static class Multiple {

    }
}

可以看到这两个类上都有EnableConfigurationBeanBindings注解,点开EnableConfigurationBeanBindings注解,发现它又使用了@Import注解引入了ConfigurationBeanBindingsRegister类。

ConfigurationBeanBindingsRegister

public class ConfigurationBeanBindingsRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware {

    private ConfigurableEnvironment environment;

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

      
      // 获取 EnableConfigurationBeanBindings 中的键值对
        AnnotationAttributes attributes = AnnotationAttributes.fromMap(
                importingClassMetadata.getAnnotationAttributes(EnableConfigurationBeanBindings.class.getName()));

      // 获取 EnableConfigurationBeanBinding 数组
        AnnotationAttributes[] annotationAttributes = attributes.getAnnotationArray("value");

      // 构建 ConfigurationBeanBindingRegistrar
        ConfigurationBeanBindingRegistrar registrar = new ConfigurationBeanBindingRegistrar();

      // 设置环境变量
        registrar.setEnvironment(environment);

      // 遍历 EnableConfigurationBeanBinding 数组
        for (AnnotationAttributes element : annotationAttributes) {
          // 调用ConfigurationBeanBindingRegistrar中的registerConfigurationBeanDefinitions方法
          // 将beanDefinition注册到Spring的beanDefinitionMap中
            registrar.registerConfigurationBeanDefinitions(element, registry);
        }
    }

    @Override
    public void setEnvironment(Environment environment) {
        Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
        this.environment = (ConfigurableEnvironment) environment;
    }
}

ConfigurationBeanBindingRegistrar

public class ConfigurationBeanBindingRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {

    final static Class ENABLE_CONFIGURATION_BINDING_CLASS = EnableConfigurationBeanBinding.class;

    private final static String ENABLE_CONFIGURATION_BINDING_CLASS_NAME = ENABLE_CONFIGURATION_BINDING_CLASS.getName();

    private final Log log = LogFactory.getLog(getClass());

    private ConfigurableEnvironment environment;

  
    /*
	 * 注册beanDefinition
	 * @param metadata
	 * @param registry 
	 * @return void 
	 */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {

      
      // 获取 EnableConfigurationBeanBinding 注解上的键值对
        Map<String, Object> attributes = metadata.getAnnotationAttributes(ENABLE_CONFIGURATION_BINDING_CLASS_NAME);

      // 注册配置bean的beanDefinition
        registerConfigurationBeanDefinitions(attributes, registry);
    }

  
  
    /*
	 * 注册配置bean的beanDefinition
	 * @param attributes
	 * @param registry 
	 * @return void 
	 */
    public void registerConfigurationBeanDefinitions(Map<String, Object> attributes, BeanDefinitionRegistry registry) {

        String prefix = getRequiredAttribute(attributes, "prefix");

        prefix = environment.resolvePlaceholders(prefix);

        Class<?> configClass = getRequiredAttribute(attributes, "type");

        boolean multiple = getAttribute(attributes, "multiple", valueOf(DEFAULT_MULTIPLE));

        boolean ignoreUnknownFields = getAttribute(attributes, "ignoreUnknownFields", valueOf(DEFAULT_IGNORE_UNKNOWN_FIELDS));

        boolean ignoreInvalidFields = getAttribute(attributes, "ignoreInvalidFields", valueOf(DEFAULT_IGNORE_INVALID_FIELDS));

      // ===================重要方法===================
        registerConfigurationBeans(prefix, configClass, multiple, ignoreUnknownFields, ignoreInvalidFields, registry);
    }


  
    /*
	 *  配置bean的beanDefinition注册
	 * 
	 * @param prefix
	 * @param configClass
	 * @param multiple 是否支持多Dubbo配置Bean绑定
	 * @param ignoreUnknownFields
	 * @param ignoreInvalidFields
	 * @param registry 
	 * @return void 
	 */
    private void registerConfigurationBeans(String prefix, Class<?> configClass, boolean multiple,
                                            boolean ignoreUnknownFields, boolean ignoreInvalidFields,
                                            BeanDefinitionRegistry registry) {

      // 从application.properties中根据前缀拿对应的配置项
        Map<String, Object> configurationProperties = PropertySourcesUtils.getSubProperties(environment.getPropertySources(), environment, prefix);

        if (CollectionUtils.isEmpty(configurationProperties)) {
            if (log.isDebugEnabled()) {
                log.debug("There is no property for binding to configuration class [" + configClass.getName()
                        + "] within prefix [" + prefix + "]");
            }
            return;
        }

      
      // multiple 表示是否支持多Dubbo 配置 Bean 绑定
      // 比如 
      /*
       dubbo.protocols.p1.id=p1 
       dubbo.protocols.p1.name=dubbo 
       dubbo.protocols.p1.port=20881 
       dubbo.protocols.p1.host=127.0.0.1 
       
       dubbo.protocols.p2.id=p2
       dubbo.protocols.p2.name=dubbo 
       dubbo.protocols.p2.port=20881 
       dubbo.protocols.p2.host=127.0.0.1 
       */ 
      // 生成多个Dubbo配置Bean,而这多个bean直接按protocols后的p1,p2命名
        Set<String> beanNames = multiple ? resolveMultipleBeanNames(configurationProperties) :
                singleton(resolveSingleBeanName(configurationProperties, configClass, registry));

        // 遍历循环
        for (String beanName : beanNames) {
          // 注册配置bean的beanDefinition
            registerConfigurationBean(beanName, configClass, multiple, ignoreUnknownFields, ignoreInvalidFields,
                    configurationProperties, registry);
        }
      
         // 注册 ConfigurationBindingBeanPostProcessor 后置处理器
         // 这样可以在bean实例化之前进行属性赋值
        registerConfigurationBindingBeanPostProcessor(registry);
    }

  
    private void registerConfigurationBean(String beanName, Class<?> configClass, boolean multiple,
                                           boolean ignoreUnknownFields, boolean ignoreInvalidFields,
                                           Map<String, Object> configurationProperties,
                                           BeanDefinitionRegistry registry) {

        // 构建BeanDefinitionBuilder
        BeanDefinitionBuilder builder = rootBeanDefinition(configClass);

        // 获取 beanDefinition
        AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();

        // 设置源头
        // 后面会bean后置处理器会通过它区分bean是否是这里引过去的
        setSource(beanDefinition);

        // 获取每项配置的键值对
        Map<String, Object> subProperties = resolveSubProperties(multiple, beanName, configurationProperties);

        // 设置beanDefinition的属性
        initBeanMetadataAttributes(beanDefinition, subProperties, ignoreUnknownFields, ignoreInvalidFields);

        // 注册beanDefinition
        registry.registerBeanDefinition(beanName, beanDefinition);

        if (log.isInfoEnabled()) {
            log.info("The configuration bean definition [name : " + beanName + ", content : " + beanDefinition
                    + "] has been registered.");
        }
    }
}

ConfigurationBeanBindingPostProcessor

ConfigurationBeanBindingPostProcessor是一个后置处理器,实现了BeanPostProcessor接口,这样就可以在bean实例化的前后对bean进行一些特殊处理。

@SuppressWarnings("unchecked")
public class ConfigurationBeanBindingPostProcessor implements BeanPostProcessor, BeanFactoryAware, PriorityOrdered {

    /**
     * The bean name of {@link ConfigurationBeanBindingPostProcessor}
     */
    public static final String BEAN_NAME = "configurationBeanBindingPostProcessor";

    static final String CONFIGURATION_PROPERTIES_ATTRIBUTE_NAME = "configurationProperties";

    static final String IGNORE_UNKNOWN_FIELDS_ATTRIBUTE_NAME = "ignoreUnknownFields";

    static final String IGNORE_INVALID_FIELDS_ATTRIBUTE_NAME = "ignoreInvalidFields";


  
    /*
	 * 前置处理
	 * @param bean
	 * @param beanName
	 * @return java.lang.Object
	 */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

        // 获取 beanDefinition
        BeanDefinition beanDefinition = getNullableBeanDefinition(beanName);

        // 判断bean是不是@EnableConfigurationBeanBinding注册的bean
        if (isConfigurationBean(bean, beanDefinition)) {
            // 属性值绑定到bean上
            bindConfigurationBean(bean, beanDefinition);
          
            customize(beanName, bean);
        }

        return bean;
    }

  
    /*
	 * 判断bean是否是通过EnableConfigurationBeanBinding路径注册的
	 * @param bean
	 * @param beanDefinition
	 * @return boolean
	 */
    private boolean isConfigurationBean(Object bean, BeanDefinition beanDefinition) {
        return beanDefinition != null &&
                ENABLE_CONFIGURATION_BINDING_CLASS.equals(beanDefinition.getSource())
                && nullSafeEquals(getBeanClassName(bean), beanDefinition.getBeanClassName());
    }

   
  
    /*
	 * 设置配置bean的属性值
	 * @param configurationBean
	 * @param beanDefinition
	 * @return void 
	 */
    private void bindConfigurationBean(Object configurationBean, BeanDefinition beanDefinition) {

        // 获取 key 为 configurationProperties 的属性值
        Map<String, Object> configurationProperties = 
          
          getConfigurationProperties(beanDefinition);
      

        // 是否忽略 UnknownFields
        boolean ignoreUnknownFields = getIgnoreUnknownFields(beanDefinition);

        //是否忽略 InvalidFields
        boolean ignoreInvalidFields = getIgnoreInvalidFields(beanDefinition);

        getConfigurationBeanBinder().bind(configurationProperties, ignoreUnknownFields, ignoreInvalidFields, configurationBean);

        if (log.isInfoEnabled()) {
            log.info("The configuration bean [" + configurationBean + "] have been binding by the " +
                    "configuration properties [" + configurationProperties + "]");
        }
    }

   
  
  private ConfigurationBeanBinder configurationBeanBinder = null;

   public ConfigurationBeanBinder getConfigurationBeanBinder() {
        if (configurationBeanBinder == null) {
          // 从Sprin容器中获取 ConfigurationBeanBinder
          // 如果出现异常,则直接 new 一个 DefaultConfigurationBeanBinder
            initConfigurationBeanBinder();
        }
        return configurationBeanBinder;
    }
  
  
    private void customize(String beanName, Object configurationBean) {
        // 遍历 
        for (ConfigurationBeanCustomizer customizer : getConfigurationBeanCustomizers()) {
            // 自定义设置配置bean的属性
            customizer.customize(beanName, configurationBean);
        }
    }

}

debug过程

DubboConfigConfigurationRegistrar#registerBeanDefinitions

好了,上面贴了这么多的方法及源码,估计现在看客们已经云里雾里了,下面就带大家debug一次,再梳理一下流程。

首先将断点设置在DubboConfigConfigurationRegistrar#registerBeanDefinitions方法的第一行,然后启动SpringBoot项目,进入断点,如下所示:

image.png

然后我们step intoregisterBeans的执行

image.png

image.png

此时控制台输出日志:

DefaultListableBeanFactory will register annotated classes : [class org.apache.dubbo.config.spring.context.annotation.DubboConfigConfiguration$Single] 

下面的就不跟踪了,属于Spring容器相关的源码了。

DubboConfigConfigurationRegistrar#registerCommonBeans

回到DubboConfigConfigurationRegistrar#registerBeanDefinitions方法,继续de bug,然后step into里面registerCommonBeans方法里面,紧接着进入BeanRegistrar#registerInfrastructureBean方法中,如下所示:

image.png

此时打印日志如下:

The Infrastructure bean definition [Root bean: class [org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=nullwith name [referenceAnnotationBeanPostProcessor] has been registered.

DubboConfigConfigurationRegistrar#registerBeanDefinitionsdebug流程大致就是这样。

ConfigurationBeanBindingsRegister#registerBeanDefinitions

DubboConfigConfigurationRegistrar#registerBeanDefinitions方法中,会将DubboConfigConfiguration.SingleDubboConfigConfiguration.MultiplebeadDefinition注册到Spring容器中。而这两个类上都有EnableConfigurationBeanBindings注解,如此所示:

image.png

最终也会将DubboCofig配置相关的类的beadDefinition注册到Spring容器的beanDefinitionMap中,从而进入到ConfigurationBeanBindingsRegister#registerBeanDefinitions的方法。在此处打个断点,进行debug,如下所示:

image.png

接着step into registrar.registerConfigurationBeanDefinitions(element, registry)行,进入到ConfigurationBeanBindingRegistrar#registerConfigurationBeanDefinitions方法

image.png

接着step into registerConfigurationBeans这个方法,直到registerConfigurationBindingBeanPostProcessor方法停止

image.png

此时日志输出:

  The configuration bean definition [name : org.apache.dubbo.config.ApplicationConfig#0, content : Root bean: class [org.apache.dubbo.config.ApplicationConfig]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] has been registered.
  
  The Infrastructure bean definition [Root bean: class [com.alibaba.spring.beans.factory.annotation.ConfigurationBeanBindingPostProcessor]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=nullwith name [configurationBeanBindingPostProcessor] has been registered.
                                      
  There is no property for binding to configuration class [org.apache.dubbo.config.ModuleConfig] within prefix [dubbo.module]

step into registerConfigurationBindingBeanPostProcessor方法

image.png

这是个向Spring容器的beanDefinitionMap中注册ConfigurationBeanBindingPostProcessor后置处理器的beanDefinition

回答问题

文章一开始的问题是,SpringBoot启动类上加上@EnableDubbo这样就可以启动Dubbo相关服务了为什么

结合本文的内容可以这么说,EnableDubbo注解是一个组合注解继承了EnableDubboConfigDubboComponentScan这两个注解EnableDubboConfig注解的作用是DubboConfig的相关配置beanbeanDefinition注入到Spring容器的beanDefinitionMap将这些bean交由Spring进行管理以便在合适的时机获取特定的bean实例

至于DubboComponentScan注解的作用我会在下一章进行讲解。

Reference

posted @ 2022-03-27 14:38  Reecelin  阅读(425)  评论(0编辑  收藏  举报