相关阅读
简介
本文基于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;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之家整理,本文链接:https://www.bmabk.com/index.php/post/4760.html