详细分析了spring是如何找到并解析配置类,如果将通过@ComponentScan 和 @Component 、@Bean 以及 @Import 注解声明的bean,自动注册的容器中的。
用于debug的源码:https://gitee.com/cq-laozhou/spring-stack-source-code-analysis
invokeBeanFactoryPostProcessors 步骤解析
本篇接着上篇,解析refresh方法中的 invokeBeanFactoryPostProcessors(beanFactory) 这个步骤,该方法会调用到 PostProcessorRegistrationDelegate的 invokeBeanFactoryPostProcessors 方法上, 这个方法就是来回调 BeanDefinitionRegistryPostProcessors 以及 BeanFactoryPostProcessor 的。
整体逻辑是:
- 调用通过 context.addBeanFactoryPostProcessor 加到容器中的 BeanDefinitionRegistryPostProcessor
- 调用实现了 PriorityOrdered 的 BeanDefinitionRegistryPostProcessor
- 调用实现了Ordered的 BeanDefinitionRegistryPostProcessor
- 调用常规的 BeanDefinitionRegistryPostProcessor ,通过循环解决BeanDefinitionRegistryPostProcessor又加入新的BeanDefinitionRegistryPostProcessor的情况。
- =====================
- 把所有的 BeanDefinitionRegistryPostProcessor 当做 BeanFactoryPostProcessor 调用
- 调用通过 context.addBeanFactoryPostProcessor 加到容器中的 BeanFactoryPostProcessor
- 调用实现了 PriorityOrdered 的 BeanFactoryPostProcessor
- 调用实现了Ordered的 BeanFactoryPostProcessor
- 调用常规的 BeanFactoryPostProcessor
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
//processedBeans用于保存已经调用过的beanName,防止重复调用。
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
//常规的BeanFactoryPostProcessor,里面放的是通过context.addBeanFactoryPostProcessor加入的BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
//里面存放所有的 BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
//通过context.addBeanFactoryPostProcessor加入的进行区分,并且如果是BeanDefinitionRegistryPostProcessor则先调用。
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
//当前的 BeanDefinitionRegistryPostProcessor 的待调用列表,会随着调动过程清除和加入。
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
//从容器中获取所有 实现了PriorityOrdered的BeanDefinitionRegistryPostProcessors。并放到当前待调用的列表中。
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//beanFactory.getBean方法是从容器中获取bean实例,这个方法会在后面单独说明。
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
//对当前待调用列表排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
//当前待调用的 BeanDefinitionRegistryPostProcessors 加入到 registryProcessors中
registryProcessors.addAll(currentRegistryProcessors);
//依次调用待调用列表中所有BeanDefinitionRegistryPostProcessors
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
//清除当前待调用列表
currentRegistryProcessors.clear();
//从容器中获取所有 实现了Ordered的BeanDefinitionRegistryPostProcessors。并放到当前待调用的列表中。
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
//对当前待调用列表排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
//当前待调用的 BeanDefinitionRegistryPostProcessors 加入到 registryProcessors中
registryProcessors.addAll(currentRegistryProcessors);
//依次调用待调用列表中所有BeanDefinitionRegistryPostProcessors
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
//清除当前待调用列表
currentRegistryProcessors.clear();
//最后,调用常规的 BeanDefinitionRegistryPostProcessors 。这儿和前面有点区别是,使用了循环来解决在 BeanDefinitionRegistryPostProcessors 中又注册了一个新的 BeanDefinitionRegistryPostProcessors 进去,确保所有的BeanDefinitionRegistryPostProcessors都会被正常调用。
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
//调用常规的逻辑和前面的两种是一样的。
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
//当所有的 BeanDefinitionRegistryPostProcessors 都被正常调用过后,就可以调用BeanFactoryPostProcessor 了
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
//首先依次调用所有 BeanDefinitionRegistryPostProcessors的postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
//然后调用通过context.addBeanFactoryPostProcessor加入的BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
//从容器中欧获取所有 BeanFactoryPostProcessor 的beanName。
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
//遍历所有的BeanFactoryPostProcessor,并分到三个List中去,分别为实现了PriorityOrdered,实现了Ordered 以及 其他的。
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
//前面已经处理过了,直接跳过。
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
//遍历调用 priorityOrderedPostProcessors 列表中的所有 BeanFactoryPostProcessor
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
//遍历调用 orderedPostProcessors 列表中的所有 BeanFactoryPostProcessor
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
//遍历调用 nonOrderedPostProcessors 列表中的所有 BeanFactoryPostProcessor
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
遍历调用 BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry的代码:
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
遍历调用 BeanFactoryPostProcessor的 postProcessBeanFactory 的代码:
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}
}
现在,我们知道spring是如何调用 BeanDefinitionRegistryPostProcessors 和 BeanFactoryPostProcessor的。
结合上一篇文章,我们知道,在初始化AnnotatedBeanDefinitionReader中,会注册一些内部的spring组件到容器中,其中第一个注册的是 ConfigurationClassPostProcessor,它是一个BeanDefinitionRegistryPostProcessor,因此它会被调用。
ConfigurationClassPostProcessor
ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法非常重要,所有我们声明的bean,都是由它将beandefinition加载到容器中的:
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
....
//处理配置声明的beandefinition。
processConfigBeanDefinitions(registry);
}
而 processConfigBeanDefinitions 方法主要是构建ConfigurationClassParser实例,然后使用循环多轮解析的方式来解析配置类,加载配置类中声明的bean定义到容器中:
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
//存放配置类的beandefinition
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
String[] candidateNames = registry.getBeanDefinitionNames();
//这段代码就是从spring容器中找出配置类的beandefinition,放入到configCandidates中。
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
//忽略一些健壮性处理的代码
......
if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
//忽略不影响理解的代码
.......
//这段代码是对bean名称生成器的设置,当用户指定了名称生成器就用用户指定的,否则使用默认的。
// Detect any custom bean name generation strategy supplied through the enclosing application context
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
//构建 ConfigurationClassParser 实例,这个类用来解析配置类。
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
//candidates 用于保存当前这一轮解析的配置类定义
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
//alreadyParsed 用于保存已经解析配置类信息
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
//注意这个循环,使用多轮解析的方式,来解决新注册进来的bean中,又有能够当做配置类的情况【注意一点的是,并不只是@Configuration的类才是配置类,有@Component @ComponentScan @Import @ImportResource @Bean方法 的类都可以当做配置类】。
do {
//真正解析当前这一轮的配置。注意@ComponentScan 扫描的beandefinition在 parse 中就已经注册到容器中了
parser.parse(candidates);
//验证
parser.validate();
//ConfigurationClassParser中所有已经解析的配置类信息,然后去除已经解析的,剩下的就是当前这一轮新解析的配置类。
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
//加载这一轮新解析的配置类中的beandefinition,注意这儿加载的是配置类本身会作为beandefinition注册,它里面的 @Bean方法 也会注册,还会调用通过@Import定义的 ImportBeanDefinitionRegistrar 。
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
//清空当前这一轮的解析的配资类定义。
candidates.clear();
//这儿通过容器中的beandefinition数量和原来的数量,来判断是否有新的beandefinition注册进来。
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
//这段代码是判断新注册进来的beandefinition中,没有被当做配置类解析过,并且如果可以当做配置类(注意spring内分为全配置类full-使用@Configuration,轻配置类lite-使用@Component,@ComponentScan @Import,@ImportSource,甚至于类中有@Bean注解的方法,这些类都会被当做配置类处理),就加入到新一轮的待解析candidates中。
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
//如果还要待解析的配置类,继续解析。
while (!candidates.isEmpty());
//忽略
....
}
ConfigurationClassParser
接下来看看 ConfigurationClassParser.parse 方法,主要是遍历解析传入的配置类beandefinition
public void parse(Set<BeanDefinitionHolder> configCandidates) {
//遍历解析传入的配置类beandefinition
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
....
}
}
调用 processConfigurationClass方法,这个方法主要是循环递归解析当前配置类,以及该配置类的超类。
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
...
//循环递归解析当前配置类,以及该配置类的超类。
// Recursively process the configuration class and its superclass hierarchy.
SourceClass sourceClass = asSourceClass(configClass);
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
this.configurationClasses.put(configClass, configClass);
}
核心的解析代码位于 doProcessConfigurationClass 方法中:
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
//处理 @PropertySource 注解
// Process any @PropertySource annotations
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
...
}
//重要!! 处理 @ComponentScan 注解,扫描的bean就是在这儿被注册到容器中的。
// Process any @ComponentScan annotations
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
//如果配置类中有 @ComponentScan 注解,立即扫描并注册。
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
//检查扫描注册的beandefinition中,如果可以当做配置类(注意spring内分为全配置类full-使用@Configuration,轻配置类lite-使用@Component,@ComponentScan @Import,@ImportSource,甚至于类中有@Bean注解的方法,这些类都会被当做配置类处理),则递归解析。
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
//重要!! 处理 @Import 注解
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), true);
...
//重要!! 处理 @Bean 注解方法。将@Bean注解的方法解析出来,加到configClass中。
// Process individual @Bean methods
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
processInterfaces(configClass, sourceClass);
//如果有父类,则返回父类的class,这回导致其调用方法processConfigurationClass循环不会退出,将其父类当做配置类,继续解析。
// Process superclass, if any
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
// No superclass -> processing is complete
return null;
}
在this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
这行代码中,会调用ComponentScanAnnotationParser.parse 方法,该方法主要是实例化ClassPathBeanDefinitionScanner,并设置相关的属性,比如basePackages、includeFilters、excludeFilters ,最后调用真正干活的doScan方法:
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
//实例化 ClassPathBeanDefinitionScanner 。
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
....
scanner.setResourcePattern(componentScan.getString("resourcePattern"));
//设置includeFilters
for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addIncludeFilter(typeFilter);
}
}
//设置 excludeFilters
for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addExcludeFilter(typeFilter);
}
}
...
return scanner.doScan(StringUtils.toStringArray(basePackages));
}
doScan方法,真正的扫描,过滤,最后注册满足的beandefinition。
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
//扫描并注册的beandefinition
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
//找到候选的beandefinition
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
//遍历找到到beandefinition,检查通过后注册到容器中。
for (BeanDefinition candidate : candidates) {
...
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
...
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
//注册
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
继续看findCandidateComponents方法,发现它会调用scanCandidateComponents方法,这个方法才是真正做扫描工作的:
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
//扫描到的spring组件。
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
//构建扫描路径
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
//扫描路径下的类都解析为Resource。
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
//遍历所有的类,如果是spring组件,则添加到candidates中。
for (Resource resource : resources) {
if (resource.isReadable()) {
try {
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
//判断当前类是不是候选spring组件
if (isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {
candidates.add(sbd);
}
}
}
}
}
}
return candidates;
}
其中 isCandidateComponent方法中就应用了excludeFilters和includeFilters,结合上一文中,ClassPathBeanDefinitionScanner实例化时,会注册默认的includeFilters,加入载@Component,这就是默认@ComponetScan会加载@Component的原理了。
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
for (TypeFilter tf : this.excludeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return false;
}
}
for (TypeFilter tf : this.includeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return isConditionMatch(metadataReader);
}
}
return false;
}
分析到这儿,通过@ComponentScan + @Component 这种方式就分析得差不多了。@Bean的处理相对简单,在 doProcessConfigurationClass 方法中,已经将有@Bean注解的方法解析出来放到ConfigurationClass中了,在一轮解析完成后,有一步this.reader.loadBeanDefinitions(configClasses);
调用,它里面包含来注册 @Bean 方法声明的beandefinition:
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
....
//注册@import的类为beandefinition,当做配置类时,要注册到容器中。
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
//注册@Bean声明的beandefinition。
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
//注册ImportedResources的
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
//调用@@import中,指定的类为ImportBeanDefinitionRegistrar时
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
跟进去看loadBeanDefinitionsForBeanMethod方法:
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
ConfigurationClass configClass = beanMethod.getConfigurationClass();
MethodMetadata metadata = beanMethod.getMetadata();
String methodName = metadata.getMethodName();
...
//获取@Bean注解信息
AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
//beanName默认是方法名的代码
// Consider name and any aliases
List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
String beanName = (!names.isEmpty() ? names.remove(0) : methodName);
// Register aliases even when overridden
for (String alias : names) {
this.registry.registerAlias(beanName, alias);
}
//初始化BeanDefinition
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
//设置BeanDefinition属性
beanDef.setResource(configClass.getResource());
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
....
String initMethodName = bean.getString("initMethod");
if (StringUtils.hasText(initMethodName)) {
beanDef.setInitMethodName(initMethodName);
}
String destroyMethodName = bean.getString("destroyMethod");
beanDef.setDestroyMethodName(destroyMethodName);
...
//注册beandefinition
this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}
@Import的解析因为分3中情况,相对来说复制一下,不过核心思路是:
- 解析处理@Import注解的所有value指定的类。
- 遍历value指定的类,
- 如果是ImportSelector,则调用其selectImports方法,将结果当做value指定的类,递归解析@Import注解。
- 如果结果是ImportBeanDefinitionRegistrar,则放到configClass中。
- 如果不是ImportSelector和ImportBeanDefinitionRegistrar,则当做配置类处理,递归解析配置类
因此,@Import注解指定的类,通常是用来指定配置类的。
看下处理@Import直接的方法 processImports :
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports) {
//遍历候选的import类
for (SourceClass candidate : importCandidates) {
//如果是ImportSelector,实例化,并调用方法,获取结果递归调用 processImports。
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class<?> candidateClass = candidate.loadClass();
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
ParserStrategyUtils.invokeAwareMethods(
selector, this.environment, this.resourceLoader, this.registry);
....
//调用selectImports方法,将返回结果传入当前方法,递归调用processImports
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
processImports(configClass, currentSourceClass, importSourceClasses, false);
}
//如果是ImportBeanDefinitionRegistrar,则实例化后,放到configClass中。
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// Candidate class is an ImportBeanDefinitionRegistrar ->
// delegate to it to register additional bean definitions
Class<?> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
ParserStrategyUtils.invokeAwareMethods(
registrar, this.environment, this.resourceLoader, this.registry);
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
//如果都不是,则当做配置类处理,递归调用processConfigurationClass解析配置类。
else {
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass));
}
}
}
回到 loadBeanDefinitionsForConfigurationClass 方法中:
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
....
//注册@import的类为beandefinition,当做配置类时,要注册到容器中。
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
//注册@Bean声明的beandefinition。
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
//注册ImportedResources的
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
//调用 @@import中,指定的类为ImportBeanDefinitionRegistrar时
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
registerBeanDefinitionForImportedConfigurationClass 和 loadBeanDefinitionsFromRegistrars 的代码简答,你可以自行分析。
到此,我们基本上分析清楚了spring是如何找到并解析配置类,如果将通过@ComponentScan 和 @Component 、@Bean 以及 @Import 注解声明的bean,自动注册的容器中的。