文章目录
ConfigurationClassPostProcessor
调用入口为AbstractApplicationContext#invokeBeanFactoryPostProcessors,在这个方法里面收集了所有BeanDefinitionRegistryPostProcessors实现类,并调用postProcessBeanDefinitionRegistry方法。我们来看下ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
//核心逻辑,重点看,重要程度5
processConfigBeanDefinitions(registry);
}
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
//获取所有的beanNames
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
// ...
//判断是否是候选的需要处理的BeanDefinition,如果是则放入容器configCandidates
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// Return immediately if no @Configuration classes were found
//如果容器为空,则直接返回
if (configCandidates.isEmpty()) {
return;
}
// Sort by previously determined @Order value, if applicable
//对需要处理的所有beanDefinition排序
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// ...
}
检查bean是否是配置类:@Configuration/@Component/@ComponentScan/@Import/@ImportResouce/方法上有@Bean
public static boolean checkConfigurationClassCandidate(
BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
String className = beanDef.getBeanClassName();
if (className == null || beanDef.getFactoryMethodName() != null) {
return false;
}
AnnotationMetadata metadata;
//如果是扫描注解产生的BeanDefinition,比如通过@Component扫描出来的BeanDefinition
if (beanDef instanceof AnnotatedBeanDefinition &&
className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
//...
}
// 这里一般是spring内部的一些PostProcessor或者其他一些类
else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
//...
}
else {
// 其他,比如通过xml解析出来的BeanDefinition
try {
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
metadata = metadataReader.getAnnotationMetadata();
}
// ...
}
//从metadata中获取Configuration注解
Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
// 如果有Configuration注解,并且proxyBeanMethods=true,就是完全匹配标识
// 这里有两种类型:full和lite,借用手机行业里的比喻:full就是高配版、lite就是低配版、青春版
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
// 如果是有Component ComponentScan Import ImportResource或者方法上面有@Bean,就是lite匹配
else if (config != null || isConfigurationCandidate(metadata)) {
// 这里要看下
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
// 如果都不是,那么就不是候选的bean了。
return false;
}
//获取@Order注解值
// 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;
}
判断bean是否有候选的注解修饰:Component ComponentScan Import ImportResource或是否方法上有@Bean
public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
// Do not consider an interface or an annotation...
if (metadata.isInterface()) {
return false;
}
// 是否有被这些候选的注解修饰:Component ComponentScan Import ImportResource
for (String indicator : candidateIndicators) {
if (metadata.isAnnotated(indicator)) {
return true;
}
}
// 是否方法上有@Bean
try {
return metadata.hasAnnotatedMethods(Bean.class.getName());
}
}
候选的注解:Component ComponentScan Import ImportResource
private static final Set<String> candidateIndicators = new HashSet<>(8);
static {
candidateIndicators.add(Component.class.getName());
candidateIndicators.add(ComponentScan.class.getName());
candidateIndicators.add(Import.class.getName());
candidateIndicators.add(ImportResource.class.getName());
}
判断完成后,我们就知道bean是否是候选bean。我么继续看processConfigBeanDefinitions方法。
// 候选BeanDefinition的解析器
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
//解析核心流程,重点看,重要程度5
//其实就是把类上面的特殊注解解析出来最终封装成beanDefinition
parser.parse(candidates);
parser.validate();
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());
}