前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >聊聊dubbo的DubboApplicationContextInitializer

聊聊dubbo的DubboApplicationContextInitializer

原创
作者头像
code4it
修改2019-08-19 17:16:16
5010
修改2019-08-19 17:16:16
举报
文章被收录于专栏:码匠的流水账

本文主要研究一下dubbo的DubboApplicationContextInitializer

DubboApplicationContextInitializer

dubbo-spring-boot-project-2.7.3/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/context/DubboApplicationContextInitializer.java

代码语言:javascript
复制
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() {
        return HIGHEST_PRECEDENCE;
    }
​
}
  • DubboApplicationContextInitializer实现了ApplicationContextInitializer, Ordered接口,initialize方法执行overrideBeanDefinitions,它往applicationContext添加了OverrideBeanDefinitionRegistryPostProcessor、DubboConfigBeanDefinitionConflictProcessor;getOrder返回的是HIGHEST_PRECEDENCE

OverrideBeanDefinitionRegistryPostProcessor

dubbo-spring-boot-project-2.7.3/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/beans/factory/config/OverrideBeanDefinitionRegistryPostProcessor.java

代码语言:javascript
复制
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 {
    }
}
  • OverrideBeanDefinitionRegistryPostProcessor实现了BeanDefinitionRegistryPostProcessor接口,其postProcessBeanDefinitionRegistry方法调用了BeanRegistrar.registerInfrastructureBean方法注册DubboConfigBeanCustomizer

BeanRegistrar

dubbo-2.7.3-sources.jar!/org/apache/dubbo/config/spring/util/BeanRegistrar.java

代码语言:javascript
复制
public class BeanRegistrar {
​
    /**
     * Register Infrastructure Bean
     *
     * @param beanDefinitionRegistry {@link BeanDefinitionRegistry}
     * @param beanType               the type of 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);
        }
​
    }
​
}
  • registerInfrastructureBean在beanDefinitionRegistry没有该beanDefinition的情况下会注册BeanDefinition.ROLE_INFRASTRUCTURE的bean

DubboConfigBeanCustomizer

dubbo-spring-boot-project-2.7.3/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/beans/factory/config/DubboConfigBeanCustomizer.java

代码语言:javascript
复制
@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;
        }
​
        return valid;
    }
}
  • DubboConfigBeanCustomizer继承了NamePropertyDefaultValueDubboConfigBeanCustomizer,其customize方法会先校验propertyName,在valid的情况下才会执行父类的customize方法

DubboConfigBeanDefinitionConflictProcessor

dubbo-spring-boot-project-2.7.3/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/beans/factory/config/DubboConfigBeanDefinitionConflictProcessor.java

代码语言:javascript
复制
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() {
        return LOWEST_PRECEDENCE;
    }
}
  • DubboConfigBeanDefinitionConflictProcessor实现了BeanDefinitionRegistryPostProcessor, Ordered接口;postProcessBeanFactory方法会执行resolveUniqueApplicationConfigBean,校验同一个beanDefinition是否会有多个实例,有的话会抛出IllegalStateException;getOrder返回的是LOWEST_PRECEDENCE

小结

DubboApplicationContextInitializer实现了ApplicationContextInitializer, Ordered接口,initialize方法执行overrideBeanDefinitions,它往applicationContext添加了OverrideBeanDefinitionRegistryPostProcessor、DubboConfigBeanDefinitionConflictProcessor;getOrder返回的是HIGHEST_PRECEDENCE

doc

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • DubboApplicationContextInitializer
  • OverrideBeanDefinitionRegistryPostProcessor
    • BeanRegistrar
      • DubboConfigBeanCustomizer
      • DubboConfigBeanDefinitionConflictProcessor
      • 小结
      • doc
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档