Spring版本:
<version>5.2.1.RELEASE</version>
上一篇:10-Spring源码解析之refresh(4)——invokeBeanFactoryPostProcessors(1)
上一篇还遗留了两个问题,这两个问题非常重要
-
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
(PriorityOrdered
) 2-3节介绍ConfigurationClassPostProcessor
类如何解析@Configuration
注解类
-
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
4节介绍ConfigurationClassPostProcessor
类如何增强配置类
那么下面我们就一步一步看它是如何做这两件事情的。这里有必要提到一个非常重要的类了:ConfigurationClassPostProcessor
。
1. ConfigurationClassPostProcessor
的类结构
想要了解一个类,那当然首当其冲应该看它所实现的接口和父类:
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware
接着为了更只管的看到这些类,我们来看看这些类的类结构吧
接下来,我们就要进入上一篇遗留下来的第一个问题了。看一下invokeBeanFactoryPostProcessors
在调用 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
(PriorityOrdered
)时所作的工作!
2. invokeBeanDefinitionRegistryPostProcessors
方法
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
从上一篇文章中,我们可以知道,进入这个方法的postProcessors
只有一个,即ConfigurationClassPostProcessor
类型的Bean
。因此在上面代码中执行postProcessor.postProcessBeanDefinitionRegistry(registry);
时,会走到ConfigurationClassPostProcessor
类的postProcessBeanDefinitionRegistry
方法中。我们进入该方法。
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
// 给registry生成一个全局唯一ID。防止重复
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);
// 进行BeanDefinition的加载。
// 3.节 具体介绍
processConfigBeanDefinitions(registry);
}
3. processConfigBeanDefinitions
方法
下面我们就开始对传入的配置类进行注解解析了。这里的配置类即:启动项目的时候传入的类:
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig_AOP.class);
从上述代码可以看出本项目中的配置类为:MainConfig_AOP
。
我们回来继续分析processConfigBeanDefinitions
的实现方式
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
// 获取已经注册到beanFactory中的beanDefinition。
// 当前有以下6个(5个内置类+1个配置类),具体参见上篇文章1.节
// internalConfigurationAnnotationProcessor
// internalAutowiredAnnotationProcessor
// internalCommonAnnotationProcessor
// internalEventListenerProcessor
// internalEventListenerFactory
// mainConfig_AOP
String[] candidateNames = registry.getBeanDefinitionNames();
//-------------------------------------------【功能一】-------------------------------------------
// 找到上面6个BeanDenition中是带有@Configuration的类, 实际就是找出internalConfigurationAnnotationProcessor
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
// 检查是否是@Configuration的类,如果是就将其放入到configCandidates变量中。
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// 如果没有@Configuration的类,直接返回
if (configCandidates.isEmpty()) {
return;
}
// Sort by previously determined @Order value, if applicable
// @Configuration的类是可以有顺序的,按照顺序进行排序
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// 我们可以更改scan和import的方式,如果没有更改默认为:扫描为首字母小写,import为全类名
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
//-------------------------------------------【功能二】-------------------------------------------
// 解析每一个被注解 @Configuration 的类
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
// 装载已经处理过的配置类,最大长度为:configCandidates.size()
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
// 核心方法 : 解析配置类,找到配置类中的@Bean @Import @Scan类信息
// 将这些信息放入到ConfigurationClass中
// -----【1】----- 3.1节 具体介绍
parser.parse(candidates);
// 校验,配置类不能是final类型的,因为在后面需要使用CGLIB生成代理类
parser.validate();
// 得到所有已经需要解析的类,【1】中会给出图片
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());
}
//-------------------------------------------【功能三】-------------------------------------------
// 核心方法 : 将配置类中的@Bean @Import @Scan类信息注册为BeanDefinition
// -----【2】----- 3.2节 具体介绍
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
candidates.clear();
// 如果registry中注册的bean的数量 大于 之前获得的数量,
// 则意味着在解析的类中还引入类其他的注解类,那么就需要对新引入的类进行解析
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());
}
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());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
根据以上代码,可以知道上述代码实现了三个功能:
- 【功能一】
- 从6个
BeanDenition
中找到中是带有@Configuration
类的BeanDefinition
- 从6个
- 【功能二】
- 通过执行
parser.parse(candidates);
解析配置类,即将配置类中标注@Bean
、@Import
等的类找出来
- 通过执行
- 【功能三】
- 通过执行
this.reader.loadBeanDefinitions(configClasses);
将功能二中找到的注解类转换为BeanDefinition
,并将其注册到beanFactory
中
- 通过执行
3.1. parser.parse(candidates)
解析配置类
public void parse(Set<BeanDefinitionHolder> configCandidates) {
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
// 由于当前是使用注解驱动,因此当前配置类属于AnnotatedBeanDefinition
if (bd instanceof AnnotatedBeanDefinition) {
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);
}
}
this.deferredImportSelectorHandler.process();
}
由于当前项目使用的是注解驱动,所以进入AnnotatedBeanDefinition
下面的parse
方法。这个方法体如下:
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(metadata, beanName));
}
它会将传入的metadata
和beanName
封装成ConfigurationClass
,然后将封装好后的ConfigurationClass
作为参数传入processConfigurationClass
中。那么我们继续看processConfigurationClass
方法做了哪些操作。
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
// 如果这个配置类已经存在了,后面又被@Import进来了,会做属性合并
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
// Otherwise ignore new imported config class; existing non-imported class overrides it.
return;
}
else {
// Explicit bean definition found, probably replacing an import.
// Let's remove the old one and go with the new one.
this.configurationClasses.remove(configClass);
this.knownSuperclasses.values().removeIf(configClass::equals);
}
}
// Recursively process the configuration class and its superclass hierarchy.
SourceClass sourceClass = asSourceClass(configClass);
do {
//-------------------------------------------【功能一】-------------------------------------------
// -----【1】----- 这个方法是核心方法 3.1.1 中详细介绍
// 解析配置类
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
//-------------------------------------------【功能二】-------------------------------------------
this.configurationClasses.put(configClass, configClass);
}
以上方法做了两个事情:
-
【功能一】
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
-> 3.1.1 具体介绍- 解析配置类
- 并将解析的结果放到
configClass
中保存
-
【功能二】
this.configurationClasses.put(configClass, configClass);
-> 3.1.2 具体介绍- 将解析之后的结果放到一个
LinkedHashMap
中保存
- 将解析之后的结果放到一个
3.1.1 sourceClass = doProcessConfigurationClass(configClass, sourceClass);
解析配置类
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
// 查看内部类
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// 先递归地处理内部类, 本项目没有增加内部类,因此暂时先不分析这一块的内容,后续再增加
processMemberClasses(configClass, sourceClass);
}
// 处理每个 @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.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// 处理每个 @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, 因此现在立刻执行扫描,获取其中的BeanDefinition
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// 对ComponentScan得到的BeanDefinition进行检查,看里面是否有需要处理的配置类,有的话进行处理
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 注解,将这个注解的类放到configClass的importBeanDefinitionRegistrars中
// 先调用 getImports(),获取sourceClass上所有@Import注解的value
processImports(configClass, sourceClass, getImports(sourceClass), true);
// 处理每个 @ImportResource 注解
// 本项目中因为使用的是AOP的例子,因此有一个@Import,
// 即在处理@EnableAspectJAutoProxy注解的时候,引入的@Import(AspectJAutoProxyRegistrar.class)
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);
}
}
// 处理每个 @Bean 注解
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
processInterfaces(configClass, sourceClass);
// 处理父类
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;
}
以上代码显示ConfigurationClassParser
类的doProcessConfigurationClass
方法主要做的事情。按照顺序依次为:
- [1] 内部配置类:找到配置类中的内部配置类,若有内部配置类,对内部配置类进行递归解析
- [2]
@PropertySource
:这个暂时我还没有用到,以后用到再补充 - [3]
@ComponentScan
:这里扫描到的Bean
,就直接register注册了!!所以在@ComponentScan
注解中的类的注册时机是非常早的!要早于其他的注解所标注的类。(通过ClassPathBeanDefinitionScanner
去的doScan
方法去扫描注册!!) - [4]
@Import
:分三种情况:- 【情况一】:普通类 放到
ConfigurationClass
中保存 - 【情况二】:实现了
ImportSelector
:放在ConfigurationClass
中保存。若实现DeferredImportSelector
会在ConfigurationClass
的deferredImportSelectorHandler
属性保存 - 【情况三】:实现了
ImportBeanDefinitionRegistrar
,放在ConfigurationClass
类的importBeanDefinitionRegistrars
属性中。(AOP
的AspectJAutoProxyRegistrar
就属于这一类)
- 【情况一】:普通类 放到
- [5]
@ImportResource
:导入XML
文件。放在ConfigurationClass
类的importedResources
属性中 - [6]
@Bean
:配置类的方法上标注@Bean
的方法。放在ConfigurationClass
类的beanMethods
属性中- 本文中在配置文件中写了2个
Bean
注解,因此在执行完这个方法的时候,可以看到ConfigurationClass
类的beanMethods
属性中有2个类。
- 本文中在配置文件中写了2个
@Configuration
@EnableAspectJAutoProxy
public class MainConfig_AOP {
@Bean
public MathCalculator calculator() {
return new MathCalculator();
}
@Bean
public LogAspects logAspects() {
return new LogAspects();
}
}
- [7]
processInterfaces
:处理配置类的接口的default
方法 - [8] 处理父类:如果父类也是配置文件,则继续处理,直到父类全部处理完
- [9]
return null
:全部处理完成后,返回null
执行到这里,我们得到了项目中完整的ConfigurationClass
,它的beanNames
为配置类的名字,它有两个beanMethods
, 有一个importBeanDefinitionRegistrars
(因为当前项目的例子是AOP的例子)。现在我们可以回溯到3.节中,我们已经执行完了3.节的【功能二】部分,下面我们继续来看3. 节【功能三】是如何实现的。
3.2 this.reader.loadBeanDefinitions(configClasses)
将注解转变为beanDefinition
执行到这里,我们已经拿到了ConfigurationClass
,它里面包含了配置类的所有解析注解内容,但是还没有把这些信息注册到beanFactory
,这一步我们就是将configClasses
中的信息转变为beanDefintiion
,然后放到beanFacttory
中。现在我们先看看目前位置beanFacttory
中的beanDefintiion
都有什么。
还是之前的那些beanDefintiion
。注意:如果我们在配置类中有@Import
注解,那么此时:beanDefintiion
中还会有@Import
注解对应的beanDefintiion
(原因在3.1节有介绍)。我们继续向下分析。
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
// 找到项目中所有@Configuration注解标注的类
for (ConfigurationClass configClass : configurationModel) {
// 根据ConfigurationClass来注册BeanDefinition
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
接下来我们看一下它是如何通过ConfigurationClas
来注册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;
}
if (configClass.isImported()) {
// 处理@Import的配置类
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
// 这里处理配置类中使用@Bean的方法对应的类
// 执行完这一步,当前的项目中的beanFactory的多了
loadBeanDefinitionsForBeanMethod(beanMethod);
}
// 注册@ImportResource进来的Bean
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
// 注册ImportBeanDefinitionRegistrar类型的
// 这里非常重要,AOP的实现全靠它了!!!这里会创建AnnotationAwareAspectJAutoProxyCreator
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
执行完loadBeanDefinitionsForBeanMethod(beanMethod);
后,beanFactory
中的BeanDefinitions
增加了2个:
执行完loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
后,beanFactory
中的BeanDefinitions
增加了1个(与AOP
有关的AnnotationAwareAspectJAutoProxyCreator
)
至此,我们已经将本篇中的第一个问题解决完了。 下面我们解决第二个问题
4. invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
这个功能实际上是利用CGLIB
来增强我们的配置类,会为Spring添加一个后置处理器:ImportAwareBeanPostProcessor
。
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
// 实际上这里的postProcessors只有一个,即ConfigurationClassPostProcessor
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}
}
我们进入ConfigurationClassPostProcessor
类的postProcessBeanFactory
方法
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + beanFactory);
}
this.factoriesPostProcessed.add(factoryId);
if (!this.registriesPostProcessed.contains(factoryId)) {
// BeanDefinitionRegistryPostProcessor hook apparently not supported...
// Simply call processConfigurationClasses lazily at this point then.
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
// 该方法的核心方法,在4.1节下面会重点介绍
enhanceConfigurationClasses(beanFactory);
// 增加后置处理器
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
4.1 enhanceConfigurationClasses
增强配置类
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
// 拿到所有的BeanDefinition(6个内置+1个配置类+2个配置类@Bean引入的类+1个与AOP有关的类),
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
// configClassAttr 拿到的是配置类
Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
MethodMetadata methodMetadata = null;
if (beanDef instanceof AnnotatedBeanDefinition) {
methodMetadata = ((AnnotatedBeanDefinition) beanDef).getFactoryMethodMetadata();
}
if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
// Configuration class (full or lite) or a configuration-derived @Bean method
// -> resolve bean class at this point...
AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
if (!abd.hasBeanClass()) {
try {
abd.resolveBeanClass(this.beanClassLoader);
}
catch (Throwable ex) {
throw new IllegalStateException(
"Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
}
}
}
// 这里判断是否是full类型的Configuration.
// full:指 @Configuration 注解的类,说明是一个完全(full)配置类
// 若类上只有 @Component,@ComponentScan,@Import 等说明是一个简化(life)配置类
if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
if (!(beanDef instanceof AbstractBeanDefinition)) {
throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
}
else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
logger.info("Cannot enhance @Configuration bean definition '" + beanName +
"' since its singleton instance has been created too early. The typical cause " +
"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
"return type: Consider declaring such methods as 'static'.");
}
// 将配置类的beanName和配置类的beanDefinition放到configBeanDefs变量中
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
if (configBeanDefs.isEmpty()) {
// nothing to enhance -> return immediately
return;
}
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
AbstractBeanDefinition beanDef = entry.getValue();
// If a @Configuration class gets proxied, always proxy the target class
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
// Set enhanced subclass of the user-specified bean class
Class<?> configClass = beanDef.getBeanClass();
// 对配置类进行CGLIB增强
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
if (logger.isTraceEnabled()) {
logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
}
// 把增强后的配置类放回去覆盖原来的
// 因此,以后我们在通过Spring的上下文getBean()到的配置类都不是原始的配置类了,而是增强后的配置类
beanDef.setBeanClass(enhancedClass);
}
}
}
5. 总结
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
的功能有三个- 【功能一】找到解析配置类的类:
internalConfigurationAnnotationProcessor
- 【功能二】利用
internalConfigurationAnnotationProcessor
解析配置类 ,将配置类中的@Import
、@ComponentScan
、@Bean
等解析出来放入到ConfigurationClas
的属性中 - 【功能三】将
ConfigurationClas
的属性中对应的类转换为BeanDefinition
,然后注册到beanFactiory
中
- 【功能一】找到解析配置类的类:
以上我们完成了invokeBeanFactoryPostProcessors
功能的分析,下一篇我们继续分析refresh
方法中的第六个方法registerBeanPostProcessors
方法。