首先进入构造方法
public ServiceAnnotationBeanPostProcessor(Set packagesToScan) {
super(packagesToScan);
}
这里将传入的packagesToScan往父类进行传递,由于它继承了ServiceClassPostProcessor,现在进入ServiceClassPostProcessor类的构造方法:
public ServiceClassPostProcessor(Set packagesToScan) {
this.packagesToScan = packagesToScan;
}
ServiceClassPostProcessor只是将传入的扫包路径赋值给packagesToScan
根据BeanPostProcessor的特性,现在进入到postProcessBeanDefinitionRegistry方法
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// @since 2.7.5
registerBeans(registry, DubboBootstrapApplicationListener.class);
Set resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);
if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
registerServiceBeans(resolvedPackagesToScan, registry);
} else {
if (logger.isWarnEnabled()) {
logger.warn(“packagesToScan is empty , ServiceBean registry will be ignored!”);
}
}
}
该方法主要做了以下几件事:
-
注册了一个DubboBootstrapApplicationListener监听,具体作用稍后再叙
-
调用resolvePackagesToScan方法解析所有包名的路径。可能包名中存在一Placeholders的特殊定义
-
调用registerServiceBeans方法进行注册
具体怎么解析包路径不在本次讨论范围,所有就先不深入了,现在直接进入到registerServiceBeans方法中
private void registerServiceBeans(Set packagesToScan, BeanDefinitionRegistry registry) {
DubboClassPathBeanDefinitionScanner scanner =
new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);
BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);
scanner.setBeanNameGenerator(beanNameGenerator);
// refactor @since 2.7.7
serviceAnnotationTypes.forEach(annotationType -> {
scanner.addIncludeFilter(new AnnotationTypeFilter(annotationType));
});
for (String packageToScan : packagesToScan) {
// Registers @Service Bean first
scanner.scan(packageToScan);
// Finds all BeanDefinitionHolders of @Service whether @ComponentScan scans or not.
Set beanDefinitionHolders =
findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);
if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {
for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
registerServiceBean(beanDefinitionHolder, registry, scanner);
}
if (logger.isInfoEnabled()) {
logger.info(beanDefinitionHolders.size() + " annotated Dubbo’s @Service Components { " +
beanDefinitionHolders +
" } were scanned under package[" + packageToScan + “]”);
}
} else {
if (logger.isWarnEnabled()) {
logger.warn(“No Spring Bean annotating Dubbo’s @Service was found under package[”
- packageToScan + “]”);
}
}
}
}
该方法有主要做了以下几件事
-
构建了一个DubboClassPathBeanDefinitionScanner对象,该对象继承自Spring的ClassPathBeanDefinitionScanner。在Spring中,ClassPathBeanDefinitionScanner是一个扫描程序,主要用来扫描Classpath下符合条件的对象,然后将对象注入到给定的registry中
-
定义一个为Bean生成名称的BeanNameGenerator,这里生成的是AnnotationBeanNameGenerator这个策略
-
将bean名称策略set到scanner中
-
添加过滤Filter,这里遍历serviceAnnotationTypes,获取到所有的过滤条件,这里是基于注解的拦截,到serviceAnnotationTypes赋值的地方,可以看到。初始化了以下三种注解作为拦截
private final static List<Class<? extends Annotation>> serviceAnnotationTypes = asList(
// @since 2.7.7 Add the @DubboService , the issue : https://github.com/apache/dubbo/issues/6007
DubboService.class,
// @since 2.7.0 the substitute @com.alibaba.dubbo.config.annotation.Service
Service.class,
// @since 2.7.3 Add the compatibility for legacy Dubbo’s @Service , the issue : https://github.com/apache/dubbo/issues/4330
com.alibaba.dubbo.config.annotation.Service.class
);
-
遍历解析后的扫描的包,调用scanner.scan(packageToScan)注册所有标注了@Service的bean注入到ioc容器中
-
调用findServiceBeanDefinitionHolders查找所有标注了@Service的Class封装成BeanDefinitionHolders,不管是否被@ComponentScan扫描
-
如果beanDefinitionHolders存在元素,遍历beanDefinitionHolders,调用registerServiceBean注册
将标注了@Service注解的bean注入到ioc容器不属于本次讨论内容,这里也不做详细说明
下面进入到findServiceBeanDefinitionHolders方法,了解一下该方法都返回了那些类型的BeanDefinitionHolder
private Set findServiceBeanDefinitionHolders(
ClassPathBeanDefinitionScanner scanner, String packageToScan, BeanDefinitionRegistry registry,
BeanNameGenerator beanNameGenerator) {
Set beanDefinitions = scanner.findCandidateComponents(packageToScan);
Set beanDefinitionHolders = new LinkedHashSet<>(beanDefinitions.size());
for (BeanDefinition beanDefinition : beanDefinitions) {
String beanName = beanNameGenerator.generateBeanName(beanDefinition, registry);
BeanDefinitionHolder beanDefinitionHolder = new BeanDefinitionHolder(beanDefinition, beanName);
beanDefinitionHolders.add(beanDefinitionHolder);
}
return beanDefinitionHolders;
}
-
首先扫描传入的packageToScan包下的所有的符合在scanner中定义的过滤注解的.class文件,封装成BeanDefinition
-
遍历扫描到的beanDefinitions,通过名称策略,为Bean生成名称,同时用Bean和名称构建成BeanDefinitionHolder,加入到beanDefinitionHolders中,返回该集合
beanDefinitionHolders