聊聊dubbo的DubboApplicationContextInitializer
序
本文主要研究一下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
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
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
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
@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
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!",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