Dubbo学习之自动配置

相关阅读

简介

本文基于Spring Boot 2.6.6dubbo-spring-boot-starter 3.0.6环境。

引入dubbo-spring-boot-starter包,就会引入其依赖dubbo-spring-boot-autoconfigure,该依赖实现了Dubbo自动配置功能,其spring.factories文件内容如下:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.apache.dubbo.spring.boot.autoconfigure.DubboRelaxedBinding2AutoConfiguration

dubbo-spring-boot-autoconfigure会引入依赖dubbo-spring-boot-autoconfigure-compatible,该依赖也存在一个spring.factories文件,其内容如下:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.apache.dubbo.spring.boot.autoconfigure.DubboAutoConfiguration,\
org.apache.dubbo.spring.boot.autoconfigure.DubboRelaxedBindingAutoConfiguration,\
org.apache.dubbo.spring.boot.autoconfigure.DubboListenerAutoConfiguration
org.springframework.context.ApplicationListener=\
org.apache.dubbo.spring.boot.context.event.WelcomeLogoApplicationListener
org.springframework.boot.env.EnvironmentPostProcessor=\
org.apache.dubbo.spring.boot.env.DubboDefaultPropertiesEnvironmentPostProcessor
org.springframework.context.ApplicationContextInitializer=\
org.apache.dubbo.spring.boot.context.DubboApplicationContextInitializer

综上可知,dubbo-spring-boot-autoconfigure引入的自动配置类如下:

  1. org.apache.dubbo.spring.boot.autoconfigure.DubboRelaxedBinding2AutoConfiguration
  2. org.apache.dubbo.spring.boot.autoconfigure.DubboAutoConfiguration
  3. org.apache.dubbo.spring.boot.autoconfigure.DubboRelaxedBindingAutoConfiguration
  4. org.apache.dubbo.spring.boot.autoconfigure.DubboListenerAutoConfiguration

DubboAutoConfiguration

DubboAutoConfiguration是Dubbo自动配置的核心类,代码如下:

// 默认开启,除非指定dubbo.enabled=false
@ConditionalOnProperty(prefix = DUBBO_PREFIX, name = "enabled", matchIfMissing = true)
@Configuration
// 在DubboRelaxedBindingAutoConfiguration之后配置
@AutoConfigureAfter(DubboRelaxedBindingAutoConfiguration.class)
// 因为配置属性类DubboConfigurationProperties
@EnableConfigurationProperties(DubboConfigurationProperties.class)
// 开启Dubbo
@EnableDubboConfig
public class DubboAutoConfiguration {

    // 存在dubbo.scan.base-packages属性,且存在"dubbo-service-class-base-packages" Bean,则引入后置处理器ServiceAnnotationPostProcessor,用于解析DubboService注解
    // Sprin Boot 2.6.6环境下,BASE_PACKAGES_BEAN_NAME由DubboRelaxedBinding2AutoConfiguration完成注入
    // Spring Boot 1.x环境下,BASE_PACKAGES_BEAN_NAME由DubboRelaxedBindingAutoConfiguration完成注入
    @ConditionalOnProperty(prefix = DUBBO_SCAN_PREFIX, name = BASE_PACKAGES_PROPERTY_NAME)
    @ConditionalOnBean(name = BASE_PACKAGES_BEAN_NAME)
    @Bean
    public ServiceAnnotationPostProcessor serviceAnnotationBeanProcessor(@Qualifier(BASE_PACKAGES_BEAN_NAME)
                                                                       Set<String> packagesToScan) {
        return new ServiceAnnotationPostProcessor(packagesToScan);
    }
}

核心功能为:

  1. 引入属性配置类DubboConfigurationProperties
  2. 通过注解EnableDubboConfig开启Dubbo功能;
  3. 注入ServiceAnnotationPostProcessor用于解析DubboService注解;

DubboConfigurationProperties

DubboConfigurationProperties声明了Dubbo中各组件的配置参数信息,核心代码如下:

@ConfigurationProperties(DUBBO_PREFIX)
public class DubboConfigurationProperties {

    @NestedConfigurationProperty
    private Config config = new Config();

    @NestedConfigurationProperty
    private Scan scan = new Scan();

    // Single Config Bindings
    @NestedConfigurationProperty
    private ApplicationConfig application = new ApplicationConfig();

    @NestedConfigurationProperty
    private ModuleConfig module = new ModuleConfig();

    @NestedConfigurationProperty
    private RegistryConfig registry = new RegistryConfig();

    @NestedConfigurationProperty
    private ProtocolConfig protocol = new ProtocolConfig();

    @NestedConfigurationProperty
    private MonitorConfig monitor = new MonitorConfig();

    @NestedConfigurationProperty
    private ProviderConfig provider = new ProviderConfig();

    @NestedConfigurationProperty
    private ConsumerConfig consumer = new ConsumerConfig();

    @NestedConfigurationProperty
    private ConfigCenterBean configCenter = new ConfigCenterBean();

    @NestedConfigurationProperty
    private MetadataReportConfig metadataReport = new MetadataReportConfig();

    @NestedConfigurationProperty
    private MetricsConfig metrics = new MetricsConfig();

    // Multiple Config Bindings

    private Map<String, ModuleConfig> modules = new LinkedHashMap<>();

    private Map<String, RegistryConfig> registries = new LinkedHashMap<>();

    private Map<String, ProtocolConfig> protocols = new LinkedHashMap<>();

    private Map<String, MonitorConfig> monitors = new LinkedHashMap<>();

    private Map<String, ProviderConfig> providers = new LinkedHashMap<>();

    private Map<String, ConsumerConfig> consumers = new LinkedHashMap<>();

    private Map<String, ConfigCenterBean> configCenters = new LinkedHashMap<>();

    private Map<String, MetadataReportConfig> metadataReports = new LinkedHashMap<>();

    private Map<String, MetricsConfig> metricses = new LinkedHashMap<>();
}

EnableDubboConfig

EnableDubboConfig的核心就是引入DubboConfigConfigurationRegistrar,代码如下:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
// 借助Import机制引入DubboConfigConfigurationRegistrar
@Import(DubboConfigConfigurationRegistrar.class)
public @interface EnableDubboConfig {

    // 现在不用了,详见DubboConfigConfigurationRegistrar
    boolean multiple() default true;
}

DubboConfigConfigurationRegistrarregisterBeanDefinitions方法就是初始化Dubbo相关的Bean,代码如下:

public class DubboConfigConfigurationRegistrar implements ImportBeanDefinitionRegistrar {

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

        // 初始化Dubbo 相关Bean
        DubboSpringInitializer.initialize(registry);

        // Config beans creating from props have move to ConfigManager
//        AnnotationAttributes attributes = AnnotationAttributes.fromMap(
//                importingClassMetadata.getAnnotationAttributes(EnableDubboConfig.class.getName()));
//
//        boolean multiple = attributes.getBoolean("multiple");
//
//        // Single Config Bindings
//        registerBeans(registry, DubboConfigConfiguration.Single.class);
//
//        if (multiple) { // Since 2.6.6 https://github.com/apache/dubbo/issues/3193
//            registerBeans(registry, DubboConfigConfiguration.Multiple.class);
//        }
    }
}

DubboSpringInitializer

DubboSpringInitializer是Dubbo Spring初始化的入口,其initialize代码如下:

public static void initialize(BeanDefinitionRegistry registry) {

    // 放入DubboSpringInitContext
    if (contextMap.putIfAbsent(registry, new DubboSpringInitContext()) != null) {
        // 若已存在,则已初始化,直接退出
        return;
    }

    DubboSpringInitContext context = contextMap.get(registry);

    // 根据BeanDefinitionRegistry查找ConfigurableListableBeanFactory
    ConfigurableListableBeanFactory beanFactory = findBeanFactory(registry);

    // 初始化DubboSpringInitContext
    initContext(context, registry, beanFactory);
}

private static void initContext(DubboSpringInitContext context, BeanDefinitionRegistry registry,
                                ConfigurableListableBeanFactory beanFactory) {
    context.setRegistry(registry);
    context.setBeanFactory(beanFactory);

    // 支持用户定制化处理DubboSpringInitContext
    customize(context);

    // 初始化ModuleModel
    ModuleModel moduleModel = context.getModuleModel();
    if (moduleModel == null) {
        // 如果当前DubboSpringInitContext中不存在ModuleModel,则使用默认值

        ApplicationModel applicationModel;
        if (findContextForApplication(ApplicationModel.defaultModel()) == null) {
            // 第一个DubboSpringInitContext使用ApplicationModel.defaultModel()
            applicationModel = ApplicationModel.defaultModel();
            logger.info("Use default application: " + safeGetModelDesc(applicationModel));
        } else {
            // 后续DubboSpringInitContext使用FrameworkModel.defaultModel().newApplication()
            applicationModel = FrameworkModel.defaultModel().newApplication();
            logger.info("Create new application: " + safeGetModelDesc(applicationModel));
        }

        moduleModel = applicationModel.getDefaultModule();
        context.setModuleModel(moduleModel);
        logger.info("Use default module model of target application: " + safeGetModelDesc(moduleModel));
    } else {
        logger.info("Use module model from customizer: " + safeGetModelDesc(moduleModel));
    }
    logger.info("Bind " + safeGetModelDesc(moduleModel) + " to spring container: " + ObjectUtils.identityToString(registry));

    if (context.getModuleAttributes().size() > 0) {
        context.getModuleModel().getAttributes().putAll(context.getModuleAttributes());
    }

    // 注册Dubbo 初始化上下文到Spring容器中
    registerContextBeans(beanFactory, context);

    // 标记绑定标识
    context.markAsBound();

    // 注册Dubbo Bean
    DubboBeanUtils.registerCommonBeans(registry);
}

DubboSpringInitializer.initContext将初始化后的DubboSpringInitContext注册到Spring容器中,用户可实现自定义DubboSpringInitCustomizer来定制化处理DubboSpringInitContext;再借助DubboBeanUtils注册其它Dubbo Bean;
DubboBeanUtils.registerCommonBeans方法代码如下:

static void registerCommonBeans(BeanDefinitionRegistry registry) {

    registerInfrastructureBean(registry, ServicePackagesHolder.BEAN_NAME, ServicePackagesHolder.class);

    registerInfrastructureBean(registry, ReferenceBeanManager.BEAN_NAME, ReferenceBeanManager.class);

    // Since 2.5.7 Register @Reference Annotation Bean Processor as an infrastructure Bean
    registerInfrastructureBean(registry, ReferenceAnnotationBeanPostProcessor.BEAN_NAME,
        ReferenceAnnotationBeanPostProcessor.class);

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

    // Since 2.7.4 Register DubboBootstrapApplicationListener as an infrastructure Bean
//        registerInfrastructureBean(registry, DubboBootstrapApplicationListener.BEAN_NAME,
//            DubboBootstrapApplicationListener.class);

    // register ApplicationListeners
    registerInfrastructureBean(registry, DubboDeployApplicationListener.class.getName(), DubboDeployApplicationListener.class);
    registerInfrastructureBean(registry, DubboConfigApplicationListener.class.getName(), DubboConfigApplicationListener.class);

    // Since 2.7.6 Register DubboConfigDefaultPropertyValueBeanPostProcessor as an infrastructure Bean
    registerInfrastructureBean(registry, DubboConfigDefaultPropertyValueBeanPostProcessor.BEAN_NAME,
        DubboConfigDefaultPropertyValueBeanPostProcessor.class);

    // Dubbo config initializer
    registerInfrastructureBean(registry, DubboConfigBeanInitializer.BEAN_NAME, DubboConfigBeanInitializer.class);

    // register infra bean if not exists later
    registerInfrastructureBean(registry, DubboInfraBeanRegisterPostProcessor.BEAN_NAME, DubboInfraBeanRegisterPostProcessor.class);
}

ServiceAnnotationPostProcessor

当存在配置参数dubbo.scan.base-packages且该参数以dubbo-service-class-base-packagesBean存在于Spring容器中,那么就需要注入ServiceAnnotationPostProcessor用于发现注解DubboService标注的类;
ServiceAnnotationPostProcessor支持的注解类型如下:

private final static List<Class<? extends Annotation>> serviceAnnotationTypes = asList(
        // @since 2.7.7 Add the @DubboService , the issue : https://github.com/apache/dubbo/issues/6007
        DubboService.class,
        // @since 2.7.0 the substitute @com.alibaba.dubbo.config.annotation.Service
        Service.class,
        // @since 2.7.3 Add the compatibility for legacy Dubbo's @Service , the issue : https://github.com/apache/dubbo/issues/4330
        com.alibaba.dubbo.config.annotation.Service.class
);

ServiceAnnotationPostProcessor实现了接口BeanFactoryPostProcessor,可用于在Bean初始化前对BeanFactory做处理;AbstractApplicationContext.refresh方法中执行invokeBeanFactoryPostProcessors(beanFactory),会执行Spring容器中所有的BeanFactoryPostProcessorServiceAnnotationPostProcessor.postProcessBeanDefinitionRegistry主要是将指定扫描包路径下的标注了Dubbo Service注解的类包装为AbstractBeanDefinition并注入Spring容器,核心代码如下:

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    this.registry = registry;
    scanServiceBeans(resolvedPackagesToScan, registry);
}

private void scanServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {

    scaned = true;
    if (CollectionUtils.isEmpty(packagesToScan)) {
        // 如果不存在指定的扫描路径,则无需扫描
        if (logger.isWarnEnabled()) {
            logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
        }
        return;
    }

    DubboClassPathBeanDefinitionScanner scanner =
            new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);

    BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);
    scanner.setBeanNameGenerator(beanNameGenerator);
    for (Class<? extends Annotation> annotationType : serviceAnnotationTypes) {
        scanner.addIncludeFilter(new AnnotationTypeFilter(annotationType));
    }

    ScanExcludeFilter scanExcludeFilter = new ScanExcludeFilter();
    scanner.addExcludeFilter(scanExcludeFilter);

    for (String packageToScan : packagesToScan) {

        // 如果已经扫描过则无需再扫描
        if (servicePackagesHolder.isPackageScanned(packageToScan)) {
            if (logger.isInfoEnabled()) {
                logger.info("Ignore package who has already bean scanned: " + packageToScan);
            }
            continue;
        }

        // 注册packageToScan包下Dubbo Service BeanDefinition
        scanner.scan(packageToScan);

        // 查找packageToScan包下所有的Dubbo Service,并包装为BeanDefinitionHolder
        Set<BeanDefinitionHolder> beanDefinitionHolders =
                findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);

        if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {
            if (logger.isInfoEnabled()) {
                List<String> serviceClasses = new ArrayList<>(beanDefinitionHolders.size());
                for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
                    serviceClasses.add(beanDefinitionHolder.getBeanDefinition().getBeanClassName());
                }
                logger.info("Found " + beanDefinitionHolders.size() + " classes annotated by Dubbo @Service under package [" + packageToScan + "]: " + serviceClasses);
            }

            for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
                // 处理经过扫描得到的BeanDefinitionHolder
                processScannedBeanDefinition(beanDefinitionHolder, registry, scanner);
                // 缓存该Class,避免再次扫描
                servicePackagesHolder.addScannedClass(beanDefinitionHolder.getBeanDefinition().getBeanClassName());
            }
        } else {
            if (logger.isWarnEnabled()) {
                logger.warn("No class annotated by Dubbo @Service was found under package ["
                        + packageToScan + "], ignore re-scanned classes: " + scanExcludeFilter.getExcludedCount());
            }
        }
        // 缓存该包,避免再次扫描

        servicePackagesHolder.addScannedPackage(packageToScan);
    }
}

private void processScannedBeanDefinition(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry,
                                          DubboClassPathBeanDefinitionScanner scanner) {

    Class<?> beanClass = resolveClass(beanDefinitionHolder);
    // 获取Dubbo Service注解
    Annotation service = findServiceAnnotation(beanClass);

    // 获取Dubbo Service注解的属性值,忽略默认值
    Map<String, Object> serviceAnnotationAttributes = AnnotationUtils.getAttributes(service, true);

    // 获取接口类
    String serviceInterface = resolveInterfaceName(serviceAnnotationAttributes, beanClass);

    String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();

    // 构造ServiceBean BeanName
    String beanName = generateServiceBeanName(serviceAnnotationAttributes, serviceInterface);

    // 构造AbstractBeanDefinition
    AbstractBeanDefinition serviceBeanDefinition =
            buildServiceBeanDefinition(serviceAnnotationAttributes, serviceInterface, annotatedServiceBeanName);

    // 注册AbstractBeanDefinition
    registerServiceBeanDefinition(beanName, serviceBeanDefinition, serviceInterface);
}

private AbstractBeanDefinition buildServiceBeanDefinition(Map<String, Object> serviceAnnotationAttributes,
                                                          String serviceInterface,
                                                          String refServiceBeanName) {

    BeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class);

    AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();

    MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();

    String[] ignoreAttributeNames = of("provider", "monitor", "application", "module", "registry", "protocol",
            "interface", "interfaceName", "parameters");

    propertyValues.addPropertyValues(new AnnotationPropertyValuesAdapter(serviceAnnotationAttributes, environment, ignoreAttributeNames));

    //set config id, for ConfigManager cache key
    //builder.addPropertyValue("id", beanName);
    // 设置ref属性
    addPropertyReference(builder, "ref", refServiceBeanName);
    // 这是interface属性
    builder.addPropertyValue("interface", serviceInterface);
    // 设置parameters属性
    builder.addPropertyValue("parameters", DubboAnnotationUtils.convertParameters((String[]) serviceAnnotationAttributes.get("parameters")));
    // 处理methods属性如果存在的话
    List<MethodConfig> methodConfigs = convertMethodConfigs(serviceAnnotationAttributes.get("methods"));
    if (!methodConfigs.isEmpty()) {
        builder.addPropertyValue("methods", methodConfigs);
    }

    // 处理provider属性如果存在的话
    String providerConfigId = (String) serviceAnnotationAttributes.get("provider");
    if (StringUtils.hasText(providerConfigId)) {
        addPropertyValue(builder, "providerIds", providerConfigId);
    }

    // 处理registry属性如果存在的话
    String[] registryConfigIds = (String[]) serviceAnnotationAttributes.get("registry");
    if (registryConfigIds != null && registryConfigIds.length > 0) {
        resolveStringArray(registryConfigIds);
        builder.addPropertyValue("registryIds", StringUtils.join(registryConfigIds, ','));
    }

    // 处理protocol属性如果存在的话
    String[] protocolConfigIds = (String[]) serviceAnnotationAttributes.get("protocol");
    if (protocolConfigIds != null && protocolConfigIds.length > 0) {
        resolveStringArray(protocolConfigIds);
        builder.addPropertyValue("protocolIds", StringUtils.join(protocolConfigIds, ','));
    }

    // TODO Could we ignore these attributes: applicatin/monitor/module ? Use global config
    // 处理monitor属性如果存在的话
    String monitorConfigId = (String) serviceAnnotationAttributes.get("monitor");
    if (StringUtils.hasText(monitorConfigId)) {
        addPropertyReference(builder, "monitor", monitorConfigId);
    }

    // deprecate application reference
//        String applicationConfigId = (String) serviceAnnotationAttributes.get("application");
//        if (StringUtils.hasText(applicationConfigId)) {
//            addPropertyReference(builder, "application", applicationConfigId);
//        }

    // 处理module属性如果存在的话
    String moduleConfigId = (String) serviceAnnotationAttributes.get("module");
    if (StringUtils.hasText(moduleConfigId)) {
        addPropertyReference(builder, "module", moduleConfigId);
    }

    return builder.getBeanDefinition();
}

DubboRelaxedBindingAutoConfiguration

DubboRelaxedBindingAutoConfiguration会注入dubbo-service-class-base-packagesBean,用于配置ServiceAnnotationPostProcessor,其配置条件如下:

// 默认开启,除非指定dubbo.enabled=false
@ConditionalOnProperty(prefix = DUBBO_PREFIX, name = "enabled", matchIfMissing = true)
// 要求类路径存在RelaxedPropertyResolver
@ConditionalOnClass(name = "org.springframework.boot.bind.RelaxedPropertyResolver")

如上所述,本类适配Spring Boot 1.x,而本文基于Spring Boot 2.6.6,故不会触发DubboRelaxedBindingAutoConfiguration自动配置;DubboRelaxedBinding2AutoConfiguration适配Spring Boot 2.0及以上;

DubboRelaxedBinding2AutoConfiguration

DubboRelaxedBindingAutoConfiguration作用一样,DubboRelaxedBinding2AutoConfiguration会注入dubbo-service-class-base-packagesBean,用于配置ServiceAnnotationPostProcessor,其配置条件如下:

// 默认开启,除非指定dubbo.enabled=false
@ConditionalOnProperty(prefix = DUBBO_PREFIX, name = "enabled", matchIfMissing = true)
// 要求类路径存在Binder
@ConditionalOnClass(name = "org.springframework.boot.context.properties.bind.Binder")
// 优先于DubboRelaxedBindingAutoConfiguration进行自动配置
@AutoConfigureBefore(DubboRelaxedBindingAutoConfiguration.class)

本文基于Spring Boot 2.6.6,故会触发DubboRelaxedBinding2AutoConfiguration自动配置,其注入Bean代码如下:

public PropertyResolver dubboScanBasePackagesPropertyResolver(ConfigurableEnvironment environment) {
    ConfigurableEnvironment propertyResolver = new AbstractEnvironment() {
        @Override
        protected void customizePropertySources(MutablePropertySources propertySources) {
            // 查找dubbo.scan相关配置参数
            Map<String, Object> dubboScanProperties = getSubProperties(environment.getPropertySources(), DUBBO_SCAN_PREFIX);
            propertySources.addLast(new MapPropertySource("dubboScanProperties", dubboScanProperties));
        }
    };
    ConfigurationPropertySources.attach(propertyResolver);
    return propertyResolver;
}

// 如果还不存在BASE_PACKAGES_BEAN_NAME就注入BASE_PACKAGES_BEAN_NAME
@ConditionalOnMissingBean(name = BASE_PACKAGES_BEAN_NAME)
@Bean(name = BASE_PACKAGES_BEAN_NAME)
public Set<String> dubboBasePackages(ConfigurableEnvironment environment) {
    // 获取dubbo.scan相关配置属性
    PropertyResolver propertyResolver = dubboScanBasePackagesPropertyResolver(environment);
    // 返回dubbo.scan.base-packages配置参数
    // 即注入到Spring容器
    return propertyResolver.getProperty(BASE_PACKAGES_PROPERTY_NAME, Set.class, emptySet());
}

// 如果还不存在RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME就注入RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME
@ConditionalOnMissingBean(name = RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME, value = ConfigurationBeanBinder.class)
@Bean(RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME)
@Scope(scopeName = SCOPE_PROTOTYPE)
public ConfigurationBeanBinder relaxedDubboConfigBinder() {
    // 注入BinderDubboConfigBinder到Spring容器
    return new BinderDubboConfigBinder();
}

DubboListenerAutoConfiguration

DubboListenerAutoConfiguration用于注册Dubbo相关的ApplicationListenerBean如果不存在的话,代码如下:

// 默认开启,除非指定dubbo.enabled=false
@ConditionalOnProperty(prefix = DUBBO_PREFIX, name = "enabled", matchIfMissing = true)
@Configuration
public class DubboListenerAutoConfiguration {

    @ConditionalOnMissingBean
    @Bean
    public DubboConfigBeanDefinitionConflictApplicationListener dubboConfigBeanDefinitionConflictApplicationListener() {
        // 注入DubboConfigBeanDefinitionConflictApplicationListener
        return new DubboConfigBeanDefinitionConflictApplicationListener();
    }

    @ConditionalOnMissingBean
    @Bean
    public AwaitingNonWebApplicationListener awaitingNonWebApplicationListener() {
        // 注入AwaitingNonWebApplicationListener
        return new AwaitingNonWebApplicationListener();
    }
}