相关阅读
简介
本文基于Spring Boot 2.6.6,dubbo-spring-boot-starter 3.0.6环境。
Dubbo中使用的BeanDefinitionRegistryPostProcessor如下:
ServiceAnnotationPostProcessor,在DubboAutoConfiguration中以BeanMethod方式注册;DubboConfigAliasPostProcessor,在DubboBeanUtils.registerCommonBeans方法中注册RootBeanDefinition;DubboInfraBeanRegisterPostProcessor,在DubboBeanUtils.registerCommonBeans方法中注册RootBeanDefinition;
这三者都未实现PriorityOrdered、Ordered接口,由ConfigurationClassPostProcessor(实现了PriorityOrdered)解析注册到容器中;
Dubbo中使用的BeanFactoryPostProcessor如下:
ReferenceAnnotationBeanPostProcessor,间接实现了Ordered接口;
Dubbo中使用的BeanPostProcessor如下:
DubboConfigDefaultPropertyValueBeanPostProcessor实现了PriorityOrdered接口,在DubboBeanUtils.registerCommonBeans方法中注册RootBeanDefinition;ReferenceAnnotationBeanPostProcessor实现了Ordered接口,在DubboBeanUtils.registerCommonBeans方法中注册RootBeanDefinition;DubboConfigAliasPostProcessor,在DubboBeanUtils.registerCommonBeans方法中注册RootBeanDefinition;
DubboConfigDefaultPropertyValueBeanPostProcessor和DubboConfigAliasPostProcessor的实例化是发生在AbstractApplicationContext。registerBeanPostProcessors方法中;
ReferenceAnnotationBeanPostProcessor的实例化是发生在DubboInfraBeanRegisterPostProcessor.postProcessBeanFactory方法中,且在ReferenceAnnotationBeanPostProcessor.postProcessBeanFactory方法中会移除自身的RootBeanDefinition,以避免在AbstractApplicationContext。registerBeanPostProcessors方法中再次实例化;
BeanFactoryPostProcessor
ServiceAnnotationPostProcessor
在postProcessBeanDefinitionRegistry方法中处理Dubbo Service注解标注的类,如:
@DubboService
public class DemoServiceImpl implements DemoService {
}
在postProcessBeanFactory方法中处理Dubbo Service注解标注的Bean(标注在BeanMethod),如:
@Bean
@DubboService
public MethodServiceImpl methodService() {
return new MethodServiceImpl();
}
同时,ServiceAnnotationPostProcessor也作为<dubbo:annotation package="" />标签的解析器,配置如下:
// DubboNamespaceHandler.java
registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser());
// AnnotationBeanDefinitionParser.java
protected Class<?> getBeanClass(Element element) {
return ServiceAnnotationPostProcessor.class;
}
postProcessBeanDefinitionRegistry
代码如下:
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
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;
}
// 扫描包路径下被Dubbo Service注解标注的类,并生成BeanDefinition
scanner.scan(packageToScan);
// 查找Dubbo Service的BeanDefinitionHolder
// 结果会在scan中缓存,故此次直接从缓存中得到
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);
// 缓存已扫描过的类
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);
}
}
主要逻辑为:
- 生成标注为Dubbo Service 的Class的
BeanDefinition并注册到容器; - 将生成的
BeanDefinition,再次注册为Dubbo ServiceBeanDefinition;
生成标注为Dubbo Service的BeanDefinition
ClassPathBeanDefinitionScanner.scan(packageToScan)内部使用doScan实现,其代码如下:
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
// 查找满足要求的候选组件Dubbo Service Class
// 对basePackage路径下所有类经过isCandidateComponent筛选
// 先经过excludeFilters(优先),再经过includeFilters
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
// 校验当前容器是否已存在该BeanDefinition
// 1. 若不存在则校验通过
// 2. 若存在,但兼容,则校验不通过
// 3. 若存在,且不兼容,则抛出异常
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
// 注册BeanDefinition,此时beanName根据原始类名生成
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
注册Dubbo Service BeanDefinition
processScannedBeanDefinition代码如下:
private void processScannedBeanDefinition(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry,
DubboClassPathBeanDefinitionScanner scanner) {
Class<?> beanClass = resolveClass(beanDefinitionHolder);
// 获取类上标注的Dubbo Service注解
Annotation service = findServiceAnnotation(beanClass);
// 获取注解的属性
Map<String, Object> serviceAnnotationAttributes = AnnotationUtils.getAttributes(service, true);
String serviceInterface = resolveInterfaceName(serviceAnnotationAttributes, beanClass);
String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();
// 构造Dubbo Service BeanName
// ServiceBean:interfaceName
String beanName = generateServiceBeanName(serviceAnnotationAttributes, serviceInterface);
// 构造Dubbo Service BeanDefinition
AbstractBeanDefinition serviceBeanDefinition =
buildServiceBeanDefinition(serviceAnnotationAttributes, serviceInterface, annotatedServiceBeanName);
// 注册Dubbo Service BeanDefinition
// 此时beanName为ServiceBean:interfaceName
registerServiceBeanDefinition(beanName, serviceBeanDefinition, serviceInterface);
}
postProcessBeanFactory
代码如下:
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
if (this.registry == null) {
// 未在postProcessBeanDefinitionRegistry中设置,则此时设置
this.registry = (BeanDefinitionRegistry) beanFactory;
}
// 处理由标注了Dubbo Service注解的BeanMethod得到的BeanDefinition
String[] beanNames = beanFactory.getBeanDefinitionNames();
for (String beanName : beanNames) {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
Map<String, Object> annotationAttributes = getServiceAnnotationAttributes(beanDefinition);
// 存在则说明BeanMethod上存在Dubbo Service注解
if (annotationAttributes != null) {
// 注册为Dubbo Service BeanDefinition
processAnnotatedBeanDefinition(beanName, (AnnotatedBeanDefinition) beanDefinition, annotationAttributes);
}
}
if (!scaned) {
// 还未扫描过,则扫描
scanServiceBeans(resolvedPackagesToScan, registry);
}
}
DubboConfigAliasPostProcessor
DubboConfigAliasPostProcessor核心功能是给AbstractConfig添加Alias,如果其id存在的话,该动作是在BeanPostProcessor.postProcessAfterInitialization方法中实现的,本文关注其接口BeanFactoryPostProcessor的实现,代码如下:
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
this.registry = registry;
}
DubboInfraBeanRegisterPostProcessor
DubboInfraBeanRegisterPostProcessor用于实例化基础Bean,如:ReferenceAnnotationBeanPostProcessor;
核心代码如下:
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
this.registry = registry;
}
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
if (registry != null) {
// 实例化ReferenceAnnotationBeanPostProcessor,用于处理ReferenceBean
ReferenceAnnotationBeanPostProcessor referenceAnnotationBeanPostProcessor = beanFactory.getBean(
ReferenceAnnotationBeanPostProcessor.BEAN_NAME, ReferenceAnnotationBeanPostProcessor.class);
beanFactory.addBeanPostProcessor(referenceAnnotationBeanPostProcessor);
// 注册PropertySourcesPlaceholderConfigurer如果容器还不存在的话
DubboBeanUtils.registerPlaceholderConfigurerBeanIfNotExists(beanFactory, registry);
}
ApplicationModel applicationModel = DubboBeanUtils.getApplicationModel(beanFactory);
ModuleModel moduleModel = DubboBeanUtils.getModuleModel(beanFactory);
// 设置applicationContext
SpringExtensionInjector.get(applicationModel).init(applicationContext);
SpringExtensionInjector.get(moduleModel).init(applicationContext);
DubboBeanUtils.getInitializationContext(beanFactory).setApplicationContext(applicationContext);
// 设置Dubbo配置参数
ConfigurableEnvironment environment = (ConfigurableEnvironment) applicationContext.getEnvironment();
SortedMap<String, String> dubboProperties = EnvironmentUtils.filterDubboProperties(environment);
applicationModel.getModelEnvironment().setAppConfigMap(dubboProperties);
// 注册ConfigManager单例
beanFactory.registerSingleton(ConfigManager.BEAN_NAME, applicationModel.getApplicationConfigManager());
}
BeanFactoryPostProcessor
ReferenceAnnotationBeanPostProcessor
ReferenceAnnotationBeanPostProcessor用于处理DubboReference注解,继承自AbstractAnnotationBeanPostProcessor,从而支持将ReferenceBean注入DubboReference注解标注的字段或者setter方法;同时实现了BeanFactoryPostProcessor接口,便于早期处理容器中已注册的Bean信息;
核心方法如下:
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String[] beanNames = beanFactory.getBeanDefinitionNames();
for (String beanName : beanNames) {
Class<?> beanType;
if (beanFactory.isFactoryBean(beanName)){
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
if (isReferenceBean(beanDefinition)) {
continue;
}
if (isAnnotatedReferenceBean(beanDefinition)) {
// 处理BeanMethod上的DubboReference注解
processReferenceAnnotatedBeanDefinition(beanName, (AnnotatedBeanDefinition) beanDefinition);
continue;
}
String beanClassName = beanDefinition.getBeanClassName();
// if (beanDefinition instanceof AnnotatedBeanDefinition) {
// AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDefinition;
// beanClassName = annotatedBeanDefinition.getFactoryMethodMetadata().getDeclaringClassName();
// }
beanType = ClassUtils.resolveClass(beanClassName, getClassLoader());
} else {
beanType = beanFactory.getType(beanName);
}
if (beanType != null) {
AnnotatedInjectionMetadata metadata = findInjectionMetadata(beanName, beanType, null);
try {
// 注入Dubbo Reference如果需要的话
prepareInjection(metadata);
} catch (BeansException e) {
throw e;
} catch (Exception e) {
throw new IllegalStateException("Prepare dubbo reference injection element failed", e);
}
}
}
if (beanFactory instanceof AbstractBeanFactory) {
List<BeanPostProcessor> beanPostProcessors = ((AbstractBeanFactory) beanFactory).getBeanPostProcessors();
for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
if (beanPostProcessor == this) {
// 本BeanPostProcessor在DubboInfraBeanRegisterPostProcessor实例化,并注册为BeanPostProcessor
// 不需要在PostProcessorRegistrationDelegate.registerBeanPostProcessors方法中再次注册
// 那么会导致BeanPostProcessorChecker统计出错
// 故此时移除BeanDefinition,这样在PostProcessorRegistrationDelegate.registerBeanPostProcessors方法中就不会被再注册
beanDefinitionRegistry.removeBeanDefinition(BEAN_NAME);
break;
}
}
}
try {
// 发布DubboConfigInitEvent事件,开始Dubbo初始化
applicationContext.publishEvent(new DubboConfigInitEvent(applicationContext));
} catch (Exception e) {
logger.warn("publish early application event failed, please upgrade spring version to 4.2.x or later: " + e);
}
}
BeanPostProcessor
DubboConfigDefaultPropertyValueBeanPostProcessor
DubboConfigDefaultPropertyValueBeanPostProcessor继承自GenericBeanPostProcessorAdapter<AbstractConfig>,故只会处理AbstractConfig Bean,主要是给AbstractConfig Bean设置id字段如果该字段还未赋值的话;
核心代码如下:
protected void processBeforeInitialization(AbstractConfig dubboConfigBean, String beanName) throws BeansException {
if (!beanName.contains("#")) {
// 设置id字段如果不存在的话
setPropertyIfAbsent(dubboConfigBean, Constants.ID, beanName);
// beanName should not be used as config name, fix https://github.com/apache/dubbo/pull/7624
//setPropertyIfAbsent(dubboConfigBean, "name", beanName);
}
}
protected void setPropertyIfAbsent(Object bean, String propertyName, String beanName) {
Class<?> beanClass = getTargetClass(bean);
PropertyDescriptor propertyDescriptor = getPropertyDescriptor(beanClass, propertyName);
if (propertyDescriptor != null) {
Method getterMethod = propertyDescriptor.getReadMethod();
if (getterMethod == null) {
return;
}
Object propertyValue = invokeMethod(getterMethod, bean);
if (propertyValue != null) {
// 字段值存在则无需操作
return;
}
Method setterMethod = propertyDescriptor.getWriteMethod();
if (setterMethod != null) {
if (Arrays.equals(of(String.class), setterMethod.getParameterTypes())) {
// 使用beanName作为该字段值
invokeMethod(setterMethod, bean, beanName);
}
}
}
}
ReferenceAnnotationBeanPostProcessor
对于BeanPostProcessor接口的方法,ReferenceAnnotationBeanPostProcessor没有特殊实现,ReferenceAnnotationBeanPostProcessor继承自AbstractAnnotationBeanPostProcessor是为了实现注入ReferenceBean功能;
DubboConfigAliasPostProcessor
DubboConfigAliasPostProcessor核心功能是给AbstractConfig Bean添加值为id字段的Alias,如果其id字段值存在的话;
核心代码如下:
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof AbstractConfig) {
String id = ((AbstractConfig) bean).getId();
if (hasText(id)
&& !nullSafeEquals(id, beanName)
&& !hasAlias(registry, beanName, id)) {
// 注册别名:ID
registry.registerAlias(beanName, id);
}
}
return bean;
}
本文详细解析了Dubbo在SpringBoot环境中的自动配置过程,包括ServiceAnnotationPostProcessor、ReferenceAnnotationBeanPostProcessor等处理器的作用。这些处理器在BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor阶段处理Dubbo的Service和Reference注解,实现服务的注册和引用。内容涵盖了扫描、注册BeanDefinition、处理注解等关键步骤,深入理解Dubbo与Spring的集成机制。

587

被折叠的 条评论
为什么被折叠?



