死磕Spring之IoC篇 - @Bean 等注解的实现原理
该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读
Spring 版本:5.1.14.RELEASE
开始阅读这一系列文章之前,建议先查看《深入了解 Spring IoC(面试题)》这一篇文章
该系列其他文章请查看:《死磕 Spring 之 IoC 篇 – 文章导读》
@Bean 等注解的实现原理
通过前面的一系列文章我们了解到 @Component
注解(及其派生注解)标注的 Class 类都会被解析成 BeanDefinition(Bean 的“前身”),然后会被初始化成 Bean 对象。那么 @Bean
注解不是 @Component
的派生注解,且用于标注方法,该注解的解析过程在前面的文章中没有提到,那么在 Spring 中是如何解析 @Bean
注解的呢?
可以先回顾一下《Spring 应用上下文 ApplicationContext》文章“BeanFactory 后置处理阶段”的小节中讲到,在创建好 BeanFactory 后会调用所有的 BeanFactoryPostProcessor 处理器对其进行后置处理。@Bean
注解就是在这个过程被解析的,解析过程大致就是遍历所有的 BeanDefinition,如果其内部包含 @Bean
标注的注解,则会将该方法解析出一个 BeanDefinition 对象并注册。当然,除了 @Bean
注解外,例如 @ComponentScan
、@Import
、@ImportResource
、@PropertySource
注解都是在该过程中进行解析的。那么接下来将分析整个的解析过程,入口在 ConfigurationClassPostProcessor
这个处理器中。
概览
主要涉及以下几个类:
-
org.springframework.context.annotation.ConfigurationClassPostProcessor
,处理 Spring 应用上下文中的配置类,解析@Bean
等注解,并进行 CGLIB 提升 -
org.springframework.context.annotation.ConfigurationClass
,根据前面提到的配置类解析出来的对象,包含各种注解的信息,例如@Bean
、@Import
-
org.springframework.context.annotation.ConfigurationClassParser
,解析配置类,生成 ConfigurationClass 对象并保存 -
org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader
,配置类中 BeanDefinition 的读取器,根据 ConfigurationClass 解析出 BeanDefinition 并注册
配置类:带有
@Configuration
注解的类,如果这个类带有@Component
|@ComponentScan
|@Import
|@ImportSource
注解,或者内部存在@Bean
的方法都算配置类
几个关键处理器的注册
处理器
关键的处理器:
-
ConfigurationClassPostProcessor
:处理 Spring 应用上下文中的配置类,解析@Bean
等注解,并进行 CGLIB 提升 -
AutowiredAnnotationBeanPostProcessor
:解析@Autowired
和@Value
注解标注的属性,获取对应属性值,进行依赖注入 -
CommonAnnotationBeanPostProcessor
:会解析@Resource
注解标注的属性,获取对应的属性值,进行依赖注入 -
EventListenerMethodProcessor
:解析@EventListener
注解标注的方法,会将其解析成 Spring 事件监听器并注册 -
DefaultEventListenerFactory
:帮助 EventListenerMethodProcessor 将@EventListener
注解标注的方法生成事件监听器
注册过程
在《BeanDefinition 的解析过程(面向注解)》文章中讲到,如果在 XML 配置文件中配置了 <context:component-scan />
标签,会通过 ClassPathBeanDefinitionScanner 扫描器进行解析;在《Spring 应用上下文 ApplicationContext》文章的“BeanFactory 创建阶段”小节中讲到,支持注解配置的 Spring 应用上下文会通过 ClassPathBeanDefinitionScanner 扫描器进行扫描。
在 ClassPathBeanDefinitionScanner 的扫描过程中会调用 AnnotationConfigUtils#registerAnnotationConfigProcessors(BeanDefinitionRegistry) 方法,如下:
public int scan(String... basePackages) {
// <1> 获取扫描前的 BeanDefinition 数量
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
// <2> 进行扫描,将过滤出来的所有的 .class 文件生成对应的 BeanDefinition 并注册
doScan(basePackages);
// Register annotation config processors, if necessary.
// <3> 如果 `includeAnnotationConfig` 为 `true`(默认),则注册几个关于注解的 PostProcessor 处理器(关键)
// 在其他地方也会注册,内部会进行判断,已注册的处理器不会再注册
if (this.includeAnnotationConfig) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
// <4> 返回本次扫描注册的 BeanDefinition 数量
return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}
我们再来看到 AnnotationConfigUtils 的这个方法,如下:
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
registerAnnotationConfigProcessors(registry, null);
}
/**
* Register all relevant annotation post processors in the given registry.
* @param registry the registry to operate on
* @param source the configuration source element (already extracted)
* that this registration was triggered from. May be {@code null}.
* @return a Set of BeanDefinitionHolders, containing all bean definitions
* that have actually been registered by this call
*/
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
// 处理 Spring 应用上下文中的配置类
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 处理 @Autowired 以及 @Value 注解
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// (条件激活)处理 JSR-250 注解 @Resource,如 @PostConstruct、@PreDestroy 等
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Processor 对象(条件激活)处理 JPA 注解场景
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 处理标注 @EventListener 的 Spring 事件监听方法
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
// 用于 @EventListener 标注的事件监听方法构建成 ApplicationListener 对象
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
}
整个过程就是将上面“处理器”小节中讲到的几个处理器进行注册
ConfigurationClassPostProcessor
org.springframework.context.annotation.ConfigurationClassPostProcessor
,BeanDefinitionRegistryPostProcessor 处理器,解析配置类
构造方法
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
private static final String IMPORT_REGISTRY_BEAN_NAME =
ConfigurationClassPostProcessor.class.getName() + ".importRegistry";
private SourceExtractor sourceExtractor = new PassThroughSourceExtractor();
private ProblemReporter problemReporter = new FailFastProblemReporter();
@Nullable
private Environment environment;
private ResourceLoader resourceLoader = new DefaultResourceLoader();
@Nullable
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory();
private boolean setMetadataReaderFactoryCalled = false;
/** 已处理过的 BeanDefinitionRegistry 的 ID */
private final Set<Integer> registriesPostProcessed = new HashSet<>();
/** 已处理过的 ConfigurableListableBeanFactory 的 ID */
private final Set<Integer> factoriesPostProcessed = new HashSet<>();
/** 用于扫描出 ConfigurationClass 中的 BeanDefinition 并注册 */
@Nullable
private ConfigurationClassBeanDefinitionReader reader;
private boolean localBeanNameGeneratorSet = false;
/* Using short class names as default bean names */
private BeanNameGenerator componentScanBeanNameGenerator = new AnnotationBeanNameGenerator();
}
实现了 BeanDefinitionRegistryPostProcessor 接口(继承了 BeanFactoryPostProcessor 接口)
在《Spring 应用上下文 ApplicationContext》文章“BeanFactory 后置处理阶段”的小节可以知道,BeanDefinitionRegistryPostProcessor 优先于 BeanFactoryPostProcessor,所以我们先来看到前者的实现
1. postProcessBeanDefinitionRegistry 方法
postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
方法,对 BeanDefinitionRegistry 的后置处理,其实这个入参就是 DefaultListableBeanFactory,如下:
@Override
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);
// 处理**配置类**
processConfigBeanDefinitions(registry);
}
使用 registry
的哈希值作为 ID 保存在 registriesPostProcessed
,保证同一个 BeanDefinitionRegistry 不会被重复处理,最后调用 processConfigBeanDefinitions(BeanDefinitionRegistry)
方法
2. processConfigBeanDefinitions 方法
processConfigBeanDefinitions(BeanDefinitionRegistry)
方法,处理配置类(过程有点长),如下:
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
// <1> 获取已有的 BeanDefinition 名称的集合
String[] candidateNames = registry.getBeanDefinitionNames();
// <2> 找出是**配置类**的 BeanDefinition 对象们
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);
}
}
// 检查是否带有 @Configuration 注解,设置 isFullConfigurationClass
// 或者带有 @Component | @ComponentScan | @Import | @ImportSource | 内部存在 @Bean 的方法,设置为 isLiteConfigurationClass
// 符合上面其中一个条件都算**配置类**,需要进行处理
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// Return immediately if no @Configuration classes were found
// <3> 没有需要处理的**配置类**则直接 `return`
if (configCandidates.isEmpty()) {
return;
}
// Sort by previously determined @Order value, if applicable
// <4> 根据 @Order 注解进行排序
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// Detect any custom bean name generation strategy supplied through the enclosing application context
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
// 探测名称为 org.springframework.context.annotation.internalConfigurationBeanNameGenerator 的自定义 Bean 名称生成器
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// Parse each @Configuration class
// <5> 创建一个 `ConfigurationClassParser` 对象,用于解析符合条件的**配置类**
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.1>
* 对所有的**配置类**进行解析,解析其内部的注解(@PropertySource、@ComponentScan、@Import、@ImportResource、@Bean)
* 每个**配置类**会生成一个 {@link ConfigurationClass} 对象
* 其中 @Bean 标注的方法转换成 {@link BeanMethod} 对象保存在 {@link ConfigurationClass#beanMethods} 集合中
*/
parser.parse(candidates);
/**
* <5.2>
* 对所有的 {@link ConfigurationClass} 对象进行校验
* Class 对象不能被 final 修饰,@Bean 标注的方法不能被 private 修饰
*/
parser.validate();
// <5.3> 获取解析出来的 ConfigurationClass 们,并移除已经处理过的对象
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
/*
* <5.4>
* 创建一个 ConfigurationClassBeanDefinitionReader 对象,用于扫描出 ConfigurationClass 中的 BeanDefinition 并注册
* 例如 @Bean 标注的方法需要注册、@ImportResource 注解配置的资源文件中配置的 Bean 需要注册
*/
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
/*
* <5.4.1>
* 扫描所有的 ConfigurationClass,注册相应的 BeanDefinition,主要有以下来源:
* 1. @Import 注解导入对象
* 2. 其内部定义的带有 @Bean 注解的方法
* 3. @ImportResource 注解导入资源
* 4. @Import 注解导入的 ImportBeanDefinitionRegistrar 接口的实现类可自定义实现注册相关 BeanDefinition
*/
this.reader.loadBeanDefinitions(configClasses);
// <5.5> 将这些 ConfigurationClass 保存至已解析的集合中
alreadyParsed.addAll(configClasses);
candidates.clear();
/*
* <6>
* 从上述过程注册的 BeanDefinition 中,找到没有还解析过的 BeanDefinition 们,再循环解析
* 例如 @Bean 标注的方法是新注册的 BeanDefinition,也可能是一个**配置类**,但是还没有被这里解析过
*/
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.
// <7> 清理上述解析过程中产生的元数据缓存
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
过程如下:
- 获取所有的 BeanDefinition 名称的集合
- 找出是配置类的 BeanDefinition 对象们,保存至
configCandidates
集合中- 判断是否已经处理过,已处理则不再处理,保证不被二次处理,否则
- 检查是否带有
@Configuration
注解,或者带有@Component
|@ComponentScan
|@Import
|@ImportSource
| 内部存在@Bean
的方法,符合前面其中一个条件都算配置类,需要进行处理
- 上一步没有找到需要处理的配置类,则直接
return
返回 - 根据 @Order 注解对
configCandidates
集合中的配置类进行排序
- 创建一个
ConfigurationClassParser
对象,用于解析符合条件的配置类,会先生成 ConfigurationClass 对象保存至其内部,然后通过ConfigurationClassBeanDefinitionReader
读取器从这些 ConfigurationClass 对象中解析出 BeanDefinition-
【核心】对所有的配置类进行解析,调用
ConfigurationClassParser#parse(Set<BeanDefinitionHolder>)
方法,解析其内部的注解(@PropertySource
、@ComponentScan
、@Import
、@ImportResource
、@Bean
)。每个配置类会生成一个ConfigurationClass
对象,其中@Bean
标注的方法转换成 BeanMethod 对象保存在 ConfigurationClass.beanMethods 集合中 - 对所有的 ConfigurationClass 对象进行校验:Class 对象不能被 final 修饰,
@Bean
标注的方法不能被 private 修饰 - 获取上面解析出来的 ConfigurationClass 们,放入
configClasses
集合中,并移除已经处理过的对象 - 创建一个
ConfigurationClassBeanDefinitionReader
对象,调用其loadBeanDefinitions(Set<ConfigurationClass>)
方法,扫描出 ConfigurationClass 中的 BeanDefinition 并注册。例如@Bean
标注的方法需要注册、@ImportResource
注解配置的资源文件中配置的 Bean 需要注册-
【核心】扫描所有的 ConfigurationClass,注册相应的 BeanDefinition,主要有以下来源:
-
@Import
注解导入对象 - 其内部定义的带有
@Bean
注解的方法 -
@ImportResource
注解导入资源 -
@Import
注解导入的 ImportBeanDefinitionRegistrar 接口的实现类可自定义实现注册相关 BeanDefinition
-
-
【核心】扫描所有的 ConfigurationClass,注册相应的 BeanDefinition,主要有以下来源:
- 将这些 ConfigurationClass 保存至
alreadyParsed
已解析的集合中
-
【核心】对所有的配置类进行解析,调用
- 从上述过程注册的 BeanDefinition 中,找到没有还解析过的 BeanDefinition 们,再循环解析。例如
@Bean
标注的方法是新注册的 BeanDefinition,也可能又是一个配置类,但是还没有被这里解析过,所以需要再次扫描,如果还有未处理的配置类则需要进行处理 - 清理上述解析过程中产生的元数据缓存,例如通过 ASM 从 .class 文件中获取到的 Class 信息,需要清理
总结:先根据配置类生成 ConfigurationClass 对象,然后根据该对象解析出 BeanDefinition 并注册
配置类:带有
@Configuration
注解的类,如果这个类带有@Component
|@ComponentScan
|@Import
|@ImportSource
注解,或者内部存在@Bean
的方法都算配置类
上面的第 5.1
和 5.4
分别对应 ConfigurationClassParser 和 ConfigurationClassBeanDefinitionReader 两个类,接下来会依次分析
3. postProcessBeanFactory 方法
postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
方法,对 ConfigurableListableBeanFactory 的后置处理,其实这个入参就是 DefaultListableBeanFactory,和 postProcessBeanDefinitionRegistry(BeanDefinitionRegistry)
方法是同一个入参,如下:
@Override
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);
}
// CGLIB 提升
enhanceConfigurationClasses(beanFactory);
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
如果这个 DefaultListableBeanFactory 没有处理过,这里会和上面的过程一样调用 processConfigBeanDefinitions(BeanDefinitionRegistry)
方法进行处理。接下来,会调用 enhanceConfigurationClasses(ConfigurableListableBeanFactory)
方法对 @Configuration
注解的配置类进行 CGLIB 提升,主要帮助实现 AOP 特性
4. enhanceConfigurationClasses 方法
enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory)
方法,对 @Configuration
注解的配置类进行 CGLIB 提升,如下:
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
/*
* 如果配置了 @Configuration 注解
*/
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {
/*
* 如果不是 AbstractBeanDefinition(Spring 内部 BeanDefinition 实现类都是它的子类),则抛出异常
*/
if (!(beanDef instanceof AbstractBeanDefinition)) {
throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
}
/*
* 如果这个 Bean 已经初始化了
*/
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'.");
}
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
if (configBeanDefs.isEmpty()) {
// nothing to enhance -> return immediately
/*
* 没有需要 CGLIB 提升的类则直接返回
*/
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);
try {
// Set enhanced subclass of the user-specified bean class
// 通过类加载器获取这个 BeanDefinition 的 Class 对象
Class<?> configClass = beanDef.resolveBeanClass(this.beanClassLoader);
if (configClass != null) {
// 通过 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()));
}
// 设置该 BeanDefinition 的 Class 对象为 CGLIB 子类(代理类),用于帮助实现 AOP 特性
beanDef.setBeanClass(enhancedClass);
}
}
}
catch (Throwable ex) {
throw new IllegalStateException("Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
}
}
}
整个过程大致就是:如果是 @Configuration
注解标注的类,则通过 CGLIB 创建一个子类(代理类)并设置到这个 BeanDefinition 的 beanClass
属性中。这样一来, @Configuration
注解标注的类就得到了 CGLIB 的提升,主要帮助实现 AOP 相关特性,这里不做详细展述,具体过程请期待后续的 Spring AOP 相关文章