ConfigurationClassPostProcessor实现BeanDefinitionRegistryPostProcessor,是spring内置的后置处理器,在bean的加载初始化过程中处理bean
ConfigurationClassPostProcessor.processConfigBeanDefinitions处理配置类
1、遍历所有的已注册的BeanDefinition,校验是否为配置候选类,判断条件是否添加如下注解
@Configuration,添加该注解的BeanDefinition,添加到该处理器的处理列表中,设置其属性configurationClass为full,后续会判断属性为full的配置类进行cglib增强,原始对象替换为代理对象,调用标注的@Bean 的方法会先从singletonObjects中获取
@Import、@Component、@ImportResource、@ComponentScan、@Bean;添加这些注解的类添加到该处理器的处理列表中,设置其属性configurationClass为lite,后续不会对该类进行cglib增强
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();//配置候选类列表
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
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)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
//checkConfigurationClassCandidate
//校验是否包含了@Configuration注解
if (isFullConfigurationCandidate(metadata)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
//校验是否包含了@Component、@Import、@ImportResource、@ComponentScan、@Bean
else if (isLiteConfigurationCandidate(metadata)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
return false;
}
// It's a full or lite configuration candidate... Let's determine the order value, if any.
Integer order = getOrder(metadata);
if (order != null) {
beanDef.setAttribute(ORDER_ATTRIBUTE, order);
}
return true;
2、创建ConfigurationClassParser解析配置候选类列表
将配置类封装成SourceClass处理配置类ConfigurationClassParser.doProcessConfigurationClass
2.1处理@PropertyResource注解,添加到propertySourceNames属性中
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");
}
}
2.2 处理@ComponentScan
ComponentScanAnnotationParser解析@ComponentScan注解,调用ClassPathBeanDefinitionScanner扫描注解指定的包,scanCandidateComponents,扫描本身包含或继承自@Component注解的类注册到beanDefinitionMap中,递归调用doProcessConfigurationClass,处理新注册的beanDefinition中包含@PropertyResource、@ComponentScan、@Import、@Bean注解的类
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) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> 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();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
//递归调用
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
//ClassPathBeanDefinitionScanner
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) {
//扫描包下的所有.class文件,获取包含有@Component注解的类
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);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
//注册到beanDefinition
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
2.3 处理@Import注解
导入的是 ImportSelector ,调用selectImports方法获取需要导入的类的全路径名称,加载导入的类,并注册到beanDefinition中,递归调用判断导入的类中是为ImportSelector实例
导入的类是ImportBeanDefinitionRegistrar,ClassConfig中添加ImportBeanDefinitionRegistrar实例
导入的类是普通类,则作为@Configuration配置类进行校验处理并注册到beanDefinitionMap 中
//处理@Import注解
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports) {
if (importCandidates.isEmpty()) {
return;
}
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
this.importStack.push(configClass);
try {
for (SourceClass candidate : importCandidates) {
//Import 导入的是 ImportSelector
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class<?> candidateClass = candidate.loadClass();
//实例化ImportSelector
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
//激活Aware方法判断是否需要进行beanName、beanClassLoader、beanFactory注入
ParserStrategyUtils.invokeAwareMethods(
selector, this.environment, this.resourceLoader, this.registry);
if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
this.deferredImportSelectors.add(
new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
}
else {
//调用selectImports方法获取需要导入的类的全路径名称
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
//加载导入的类,并注册到beanDefinition中
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
//递归调用判断导入的类中是为ImportSelector实例
processImports(configClass, currentSourceClass, importSourceClasses, false);
}
}//导入的类是ImportBeanDefinitionRegistrar
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);
//激活Aware方法判断是否需要进行beanName、beanClassLoader、beanFactory注入
ParserStrategyUtils.invokeAwareMethods(
registrar, this.environment, this.resourceLoader, this.registry);
//ClassConfig中添加ImportBeanDefinitionRegistrar实例
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
//导入的类是普通类,则作为@Configuration配置类进行校验处理并注册到beanDefinitionMap 中
processConfigurationClass(candidate.asConfigClass(configClass));
}
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]", ex);
}
finally {
this.importStack.pop();
}
}
}
2.4 处理@ImportResource
解析导入的文件放入ConfigClass的importedResources集合中
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);
}
}
2.5 处理@Bean
检索添加@Bean的方法,添加到ConfigClass中的beanMethods的set集合中
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
3、ConfigurationClassBeanDefinitionReader.loadBeanDefinitions
加载解析后封装到配置类ConfigurationClass属性中的beanDefinition
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;
}
//configurationClass本身是通过@Import注册的,将自身注册到beanDefinition中
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
//注册@Bean方法到beanDefinition
//注册的beanDefinition的key为方法名,值为ConfigurationClassBeanDefinition
//beanDef.setFactoryBeanName(configClass.getBeanName());
//beanDef.setUniqueFactoryMethodName(methodName);
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
//注册通过@ImportResource注解导入的,通过XmlBeanDefinitionReader.loadBeanDefinitions加载解析xml配置文件
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
//调用ImportBeanDefinitionRegistrar的registerBeanDefinitions完成注册到beanDefinition
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}