sequence

In this paper, we study the dubbo DubboApplicationContextInitializer

DubboApplicationContextInitializer

Dubbo – spring – the boot – project – 2.7.3 / dubbo – spring – the boot – compatible/autoconfigure/SRC/main/Java/org/apache/dubbo/spring/boot/co ntext/DubboApplicationContextInitializer.java

public class DubboApplicationContextInitializer implements ApplicationContextInitializer, Ordered {

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        overrideBeanDefinitions(applicationContext);
    }

    private void overrideBeanDefinitions(ConfigurableApplicationContext applicationContext) {
        applicationContext.addBeanFactoryPostProcessor(new OverrideBeanDefinitionRegistryPostProcessor());
        applicationContext.addBeanFactoryPostProcessor(new DubboConfigBeanDefinitionConflictProcessor());
    }

    @Override
    public int getOrder() {
        returnHIGHEST_PRECEDENCE; }}Copy the code
  • DubboApplicationContextInitializer implements ApplicationContextInitializer Ordered interface, the initialize method performs overrideBeanDefinitions, It add OverrideBeanDefinitionRegistryPostProcessor to applicationContext, DubboConfigBeanDefinitionConflictProcessor; GetOrder returns HIGHEST_PRECEDENCE

OverrideBeanDefinitionRegistryPostProcessor

Dubbo – spring – the boot – project – 2.7.3 / dubbo – spring – the boot – compatible/autoconfigure/SRC/main/Java/org/apache/dubbo/spring/boot/be ans/factory/config/OverrideBeanDefinitionRegistryPostProcessor.java

public class OverrideBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        registerInfrastructureBean(registry, BEAN_NAME, DubboConfigBeanCustomizer.class);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    }
}
Copy the code
  • OverrideBeanDefinitionRegistryPostProcessor BeanDefinitionRegistryPostProcessor interface is achieved, Its postProcessBeanDefinitionRegistry method calls the BeanRegistrar. Registered DubboConfigBeanCustomizer registerInfrastructureBean method

BeanRegistrar

Dubbo – 2.7.3 – sources. The jar! /org/apache/dubbo/config/spring/util/BeanRegistrar.java

public class BeanRegistrar {

    /**
     * Register Infrastructure Bean
     *
     * @param beanDefinitionRegistry {@link BeanDefinitionRegistry}
     * @param beanType               the typeof bean * @param beanName the name of bean */ public static void registerInfrastructureBean(BeanDefinitionRegistry beanDefinitionRegistry, String beanName, Class<? > beanType) {if(! beanDefinitionRegistry.containsBeanDefinition(beanName)) { RootBeanDefinition beanDefinition = new RootBeanDefinition(beanType); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition); }}}Copy the code
  • RegisterInfrastructureBean beanDefinitionRegistry in the absence of the beanDefinition registers beanDefinition. ROLE_INFRASTRUCTURE bean

DubboConfigBeanCustomizer

Dubbo – spring – the boot – project – 2.7.3 / dubbo – spring – the boot – compatible/autoconfigure/SRC/main/Java/org/apache/dubbo/spring/boot/be ans/factory/config/DubboConfigBeanCustomizer.java

@Deprecated class DubboConfigBeanCustomizer extends NamePropertyDefaultValueDubboConfigBeanCustomizer { @Override public  void customize(String beanName, AbstractConfig dubboConfigBean) { boolean valid = isValidPropertyName(dubboConfigBean, beanName);if (valid) {
            super.customize(beanName, dubboConfigBean);
        }
    }

    private boolean isValidPropertyName(AbstractConfig dubboConfigBean, String propertyValue) {
        boolean valid = true;
        String propertyName = "name";
        // AbstractConfig.checkName(String,String)
        Method method = findMethod(AbstractConfig.class, "checkName", String.class, String.class);
        try {
            if(! method.isAccessible()) { method.setAccessible(true);
            }
            if(BeanUtils.getPropertyDescriptor(dubboConfigBean.getClass(), propertyName) ! = null) { invokeMethod(method, null, propertyName, propertyValue); } } catch (IllegalStateException e) { valid =false;
        }

        returnvalid; }}Copy the code
  • DubboConfigBeanCustomizer inherited NamePropertyDefaultValueDubboConfigBeanCustomizer, it will first check propertyName customize method, The customize method of the parent class is executed only if it is valid

DubboConfigBeanDefinitionConflictProcessor

Dubbo – spring – the boot – project – 2.7.3 / dubbo – spring – the boot – compatible/autoconfigure/SRC/main/Java/org/apache/dubbo/spring/boot/be ans/factory/config/DubboConfigBeanDefinitionConflictProcessor.java

public class DubboConfigBeanDefinitionConflictProcessor implements BeanDefinitionRegistryPostProcessor, Ordered {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    private BeanDefinitionRegistry registry;

    private Environment environment;

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        this.registry = registry;
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        resolveUniqueApplicationConfigBean(registry, beanFactory);
    }

    /**
     * Resolve the unique {@link ApplicationConfig} Bean
     *
     * @param registry    {@link BeanDefinitionRegistry} instance
     * @param beanFactory {@link ConfigurableListableBeanFactory} instance
     * @see EnableDubboConfig
     */
    private void resolveUniqueApplicationConfigBean(BeanDefinitionRegistry registry,
                                                    ConfigurableListableBeanFactory beanFactory) {

        this.environment = beanFactory.getBean(ENVIRONMENT_BEAN_NAME, Environment.class);

        String[] beansNames = beanNamesForTypeIncludingAncestors(beanFactory, ApplicationConfig.class);

        if (beansNames.length < 2) { // If the number of ApplicationConfig beans is less than two, return immediately.
            return;
        }

        // Remove ApplicationConfig Beans that are configured by "dubbo.application.*"
        Stream.of(beansNames)
                .filter(this::isConfiguredApplicationConfigBeanName)
                .forEach(registry::removeBeanDefinition);

        beansNames = beanNamesForTypeIncludingAncestors(beanFactory, ApplicationConfig.class);

        if (beansNames.length > 1) {
            throw new IllegalStateException(String.format("There are more than one instances of %s, whose bean definitions : %s",
                    ApplicationConfig.class.getSimpleName(),
                    Stream.of(beansNames)
                            .map(registry::getBeanDefinition)
                            .collect(Collectors.toList()))
            );
        }
    }

    private boolean isConfiguredApplicationConfigBeanName(String beanName) {
        boolean removed = BeanFactoryUtils.isGeneratedBeanName(beanName)
                // Dubbo ApplicationConfig id as bean name
                || Objects.equals(beanName, environment.getProperty("dubbo.application.id"));

        if (removed) {
            if (logger.isWarnEnabled()) {
                logger.warn("The {} bean [ name : {} ] has been removed!", ApplicationConfig.class.getSimpleName(), beanName); }}return removed;
    }


    @Override
    public int getOrder() {
        returnLOWEST_PRECEDENCE; }}Copy the code
  • DubboConfigBeanDefinitionConflictProcessor implements BeanDefinitionRegistryPostProcessor Ordered interface; PostProcessBeanFactory method performs resolveUniqueApplicationConfigBean, check whether the same beanDefinition can have multiple instances, so throws an IllegalStateException; GetOrder returns LOWEST_PRECEDENCE

summary

DubboApplicationContextInitializer implements ApplicationContextInitializer Ordered interface, the initialize method performs overrideBeanDefinitions, It add OverrideBeanDefinitionRegistryPostProcessor to applicationContext, DubboConfigBeanDefinitionConflictProcessor; GetOrder returns HIGHEST_PRECEDENCE

doc

  • DubboApplicationContextInitializer