Spring @Configuration 注册 Bean
Spring @Configuration 注册 Bean
1. 知识大纲
重点类 / 方法 | 作用 |
---|---|
AnnotationConfigUtils#registerAnnotationConfigProcessors | 注册几个基础 BeanDefinitionRegistryPostProcessor ,其中包括 ConfigurationClassPostProcessor |
ConfigurationClassPostProcessor | 负责处理 BeanDefinitionRegistry 中注册的 BeanDefinition 中是 Configuration 配置类的 configCandidates ,并用之构建 BeanDefinitionHolder |
ConfigurationClassParser | 1. 负责处理 BeanDefinitionHolder 2. 负责解析 @Configuration 配置,将其解析为 ConfigurationClass 对象 |
ConfigurationClassBeanDefinitionReader | 注册 ConfigurationClass |
注意:通过注解注册的 Bean,分为 两种:
- full:
@Configuration
注册的 Bean或者
版本升级后@Configuration + @Bean(proxyBeanMethods=true)
(得到的是获得增强的代理类
)注册的 Bean- lite:其他方式
2. AnnotationConfigUtils#registerAnnotationConfigProcessors
-
XML 配置:
annotation-config
(AnnotationConfigBeanDefinitionParser
) 和component-scan
(ComponentScanBeanDefinitionParser
) 解析均会调用 -
注解配置:
AnnotatedBeanDefinitionReader
实例化时调用public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); Assert.notNull(environment, "Environment must not be null"); this.registry = registry; this.conditionEvaluator = new ConditionEvaluator(registry, environment, null); //自己负责注册 AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); }
ClassPathBeanDefinitionScanner#scan
调用public int scan(String... basePackages) { int beanCountAtScanStart = this.registry.getBeanDefinitionCount(); //只负责扫描候选 Component 组件类,具体的注册由调用方自己实现 doScan(basePackages); // Register annotation config processors, if necessary. if (this.includeAnnotationConfig) { AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); } return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart); }
3. ConfigurationClassPostProcessor
部分伪代码如下:
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
//获取注册的 BeanDefinition
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
//如果是 @Configuration 相关配置的类
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
4. ConfigurationClassParser
Spring
对于通过注解
@Configuration注册的类有着特定而统一的类描述,即
ConfigurationClass`,其伪代码结构如下:
//注解元数据
private final AnnotationMetadata metadata;
//资源文件
private final Resource resource;
@Nullable
private String beanName;
//对应 @Import + XXX.class ,importedBy:注解 @Import 标注的类
private final Set<ConfigurationClass> importedBy = new LinkedHashSet<>(1);
//对应 @Bean 注解
private final Set<BeanMethod> beanMethods = new LinkedHashSet<>();
//对应 @ImportResource 注解
private final Map<String, Class<? extends BeanDefinitionReader>> importedResources =
new LinkedHashMap<>();
//对应 @Import + ImportBeanDefinitionRegistrar 接口
private final Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars =
new LinkedHashMap<>();
final Set<String> skippedBeanMethods = new HashSet<>();
针对类
ConfigurationClass
的解析具体分为几种情况:
public void parse(Set<BeanDefinitionHolder> configCandidates) {
this.deferredImportSelectors = new LinkedList<>();
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
//针对类 `ConfigurationClass` 的解析具体分为几种情况:
if (bd instanceof AnnotatedBeanDefinition) {
//@Import / @ImportResource
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
//DeferredImportSelector 是 ImportSelector 的变种,其设计目的是在所有其他的配置类被处理后才处理。
processDeferredImportSelectors();
}
方法
doProcessConfigurationClass()
是对一个配置类执行的真正的处理,具体逻辑如下:
-
处理配置类
内嵌的配置类
一个配置类的成员类(配置类内嵌套定义的类)也可能是配置类,先遍历这些成员配置类,调用
processConfigurationClass
处理它们 -
@Configuration + @PropertySources
-
@Configuration + @ComponentScans
-
@Configuration + @Import
-
@Configuration + @ImportResource
解析并添加到
ConfigurationClass
中importedResources
,到后期ConfigurationClassBeanDefinitionReader#loadBeanDefinitions
注册 Bean时,使用相应的
BeanDefinitionReader
加载资源 -
@Configuration + @Bean
-
处理配置类所实现接口的缺省方法
-
检查父类是否需要处理,如果父类需要处理返回父类,否则返回 null
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
// Recursively process any member (nested) classes first,首先递归处理嵌套类
processMemberClasses(configClass, sourceClass);
// Process any @PropertySource annotations,处理每个@PropertySource注解
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// Process any @ComponentScan annotations,处理每个@ComponentScan注解
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,现在执行扫描,获取其中的Bean定义
// this.componentScanParser 是一个 ComponentScanAnnotationParser,在当前对象的构造函数中
// 被创建
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// 对Component scan得到的Bean定义做检查,看看里面是否有需要处理的配置类,
// 有的话对其做分析处理
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
if (ConfigurationClassUtils.checkConfigurationClassCandidate(
holder.getBeanDefinition(), this.metadataReaderFactory)) {
// 如果该Bean定义是一个配置类,它进行分析
parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
}
}
}
}
// Process any @Import annotations,处理每个@Import注解
// 注意这里调用到了getImports()方法,它会搜集sourceClass上所有的@Import注解的value值,
// 具体搜集的方式是访问sourceClass直接注解的@Import以及递归访问它的注解中隐含的所有的@Import
processImports(configClass, sourceClass, getImports(sourceClass), true);
// Process any @ImportResource annotations,处理每个@ImportResource注解
if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
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,处理配置类中每个带有@Bean注解的方法
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces,处理接口上的缺省方法
processInterfaces(configClass, sourceClass);
// Process superclass, if any
// 如果父类superclass存在,并且不是`java`包中的类,并且尚未处理处理,
// 则才返回它以便外层循环继续
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (!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;// 用返回null告诉外层循环结束
}
5. ConfigurationClassBeanDefinitionReader
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
/**
* Read a particular {@link ConfigurationClass}, registering bean definitions
* for the class itself and all of its {@link Bean} methods.
*/
private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass,
TrackedConditionEvaluator trackedConditionEvaluator) {
if (trackedConditionEvaluator.shouldSkip(configClass)) {
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
return;
}
//@Import
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
//@Bean
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
//@ImportResource
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
//ImportBeanDefinitionRegistrar 接口
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}