本文使用的SpringBoot环境,默认使用的是AnnotationConfigApplicationContext上下文对象
一般我们使用@Bean一般都写在@Configuration注释的类下,Spring会帮我们将@Bean注释的方法返回的对象添加进容器中
如:
@Configuration
public class MyMapperConfig {
@Bean
public Car car(){
return new Car();
}
}
Tip
如果看过Spring源码或者已经了解扫描注解的过程可以直接看源码,下面我指出了几个位置
封装BeanMethod位置ConfigurationClassParser 的 doProcessConfigurationClass() 方法。此方法将类的方法封装为BeanMethod
BeanMethod转换为BeanDefinitionConfigurationClassBeanDefinitionReader 的 loadBeanDefinitionsForBeanMethod() 方法
如何搜索到@Bean注释的方法?Spring源码一般都会从refresh方法开始调试
在AbstractApplicationContext 的refresh()方法中会执行如下代码,注册BeanDefinition
// Invoke factory processors registered as beans in the context. // 调用在上下文中注册为 bean 的工厂处理器 invokeBeanFactoryPostProcessors(beanFactory);
由于context默认注入了ConfigurationClassPostProcessor 类,会进入processConfigBeanDefinitions()方法,该方法中会使用ConfigurationClassParser类的parse方法进行解析
// Parse each @Configuration class ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); Setcandidates = new linkedHashSet<>(configCandidates); Set alreadyParsed = new HashSet<>(configCandidates.size()); do { // 解析 parser.parse(candidates); parser.validate(); Set 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()); } this.reader.loadBeanDefinitions(configClasses); alreadyParsed.addAll(configClasses);
parse()方法最终会调用到本类(ConfigurationClassParser) 的doProcessConfigurationClass() 方法,此时看到我们常见的 @Component , @ComponentScan 等注解,下面展示了该方法的部分代码
if (configClass.getmetadata().isAnnotated(Component.class.getName())) {
// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass, filter);
}
// 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);
}
else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getmetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// Process any @ComponentScan annotations
// 处理任何@ComponentScan 注释
Set componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getmetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionevaluator.shouldSkip(sourceClass.getmetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
// 调用ComponentScanAnnotationParser类的parse方法根据配置解析带有@Component的类
// 注意@Configuration中也含有@Component
Set scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getmetadata().getClassName());
// 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();
}
// 检查是否带有@Configuration注解
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// Process any @import annotations
processimports(configClass, sourceClass, getimports(sourceClass), filter, true);
// Process any @importResource annotations
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getmetadata(), importResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addimportedResource(resolvedResource, readerClass);
}
}
// Process individual @Bean methods
Set beanMethods = retrieveBeanMethodmetadata(sourceClass);
for (Methodmetadata methodmetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodmetadata, configClass));
}
上面代码中处理任何@ComponentScan 注释时会默认扫描入口类所在的包及其子包,扫描带有@Component的类。检查扫描后的定义集,以获取任何进一步的配置类,并在需要时递归解析。
在parse方法中执行到下面这段代码时,将会处理单个 @Bean 方法,将@Bean注释的方法添加进配置类中。
// Process individual @Bean methods
//retrieveBeanMethodmetadata方法 检索所有 @Bean方法的元数据
Set beanMethods = retrieveBeanMethodmetadata(sourceClass);
for (Methodmetadata methodmetadata : beanMethods) {
// 将其封装为BeanMethod并添加进配置类中
configClass.addBeanMethod(new BeanMethod(methodmetadata, configClass));
}
ConfigurationClassPostProcessor 解析完后,从配置类中加载BeanDefinition
SetconfigClasses = 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()); } // 从配置类中加载 this.reader.loadBeanDefinitions(configClasses); alreadyParsed.addAll(configClasses);
从BeanMethod转换为BeanDefinition的过程可以参考 ConfigurationClassBeanDefinitionReader 的loadBeanDefinitionsForBeanMethod()方法
最后Spring容器会实例化这些BeanDefinition
本人能力有限,如有错误望大神指正。



