Spring @Configuration 注解的源码分析

Configuration 注解是 Spring 中常用的注解,在一般的应用场景中,它用于标识一个类作为配置类,搭配 Bean 注解将创建的 bean 交给 Spring 容器管理。神奇的是,被 Bean 注解标注的方法,只会被真正调用一次。这种方法调用被拦截的情况很容易让人联想到代理,如果你在 Debug 时注意过配置类的实例,你会发现配置类的 Class 名称中携带 EnhancerBySpringCGLIB。本文将从源码角度,分析 Configuration 注解是如何工作的。

测试用例

  • 配置类
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @Configuration
    public class BeanConfig {

    @Bean
    public Person lisi() {
    return new Person("lisi", 20);
    }

    @Bean(value = "customName")
    public Person person() {
    // 测试 lisi() 在配置类拥有注解 @Configuration 时只会真正执行一次
    lisi();
    return new Person("wangwu", 30);
    }
    }
  • 测试类
    1
    2
    3
    4
    5
    6
    7
    @Test
    public void annotationConfigTest() {
    ApplicationContext ac = new AnnotationConfigApplicationContext(BeanConfig.class);
    BeanConfig beanConfig = (BeanConfig) ac.getBean("beanConfig");
    // 即使通过 beanConfig 调用,也不会执行第二次
    Person lisi = beanConfig.lisi();
    }

解析配置类

什么是配置类?

通常情况下,我们称被 Configuration 注解标注的类为配置类。事实上,配置类的范围比这个定义稍微广泛一些,可以划分为全配置类和精简配置类。在解析配置类时,我们再进一步说明。

1
2
3
4
5
6
7
8
ApplicationContext ac = new AnnotationConfigApplicationContext(BeanConfig.class);

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
// 注册类,几乎可以说无条件地注册 annotatedClasses 的 bean 定义
register(annotatedClasses);
refresh();
}

本文不详细介绍配置类本身如何注册到 BeanFactory 中。当 BeanConfig 被传递给 AnnotationConfigApplicationContext,自身会先被解析为 BeanDefinition 注册到 beanFactory 中。有两点需要注意:

  1. annotatedClasses 可以传入多个,意味着一开始静态指定的配置类可以有多个。
  2. annotatedClasses 除了在命名上提示用户应传入被注解的类外,register(annotatedClasses) 实际上只是将它们视作普通的 Bean 注册到 beanFactory 中。它们是从外界传入的**首批 BeanDefinition**。

之后 Spring 进入 refresh 流程。使用 IDEA Debug 观察此时的 beanDefinitionMap,除了 beanConfig 外,AnnotationConfigApplicationContext 在创建时,已经自动注册了 6bean 定义,其中一个就是我们今天的主角 org.springframework.context.annotation.internalConfigurationAnnotationProcessor -> org.springframework.context.annotation.ConfigurationClassPostProcessor。显而易见,此时配置类还未被处理得到新的 bean 定义。

配置类后处理器 ConfigurationClassPostProcessor

配置类后处理器 ConfigurationClassPostProcessor 实现了接口 BeanDefinitionRegistryPostProcessor,也因此同时实现了接口 BeanFactoryPostProcessor。在Spring 应用 context 刷新流程中,我们介绍过这两个接口,它们作为工厂后处理器,被用于 refresh 过程的调用工厂后处理器阶段invokeBeanFactoryPostProcessors(beanFactory))。工厂后处理器的作用,一言以蔽之,允许自定义修改应用上下文中的 bean 定义。

配置类后处理器 ConfigurationClassPostProcessor 的具体作用可以概括为两点:

  1. 解析配置类中配置的 Bean,将它们的 bean 定义注册到 BeanFactory 中。
  2. (如有必要)增强配置类

处理配置类的核心方法 processConfigBeanDefinitions

根据之前的介绍,进入 invokeBeanFactoryPostProcessors(beanFactory)ConfigurationClassPostProcessor 会先作为 BeanDefinitionRegistryPostProcessor 被调用。

个人的理解是,先将 BeanFactory 视作 BeanDefinitionRegistry 注册好 BeanDefinition,再视作 BeanFactory 进行处理,有点预备好原材料再统一处理的意思。

1
2
3
4
5
6
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
// ...
// 处理配置的 BeanDefinition
processConfigBeanDefinitions(registry);
}

核心方法 processConfigBeanDefinitions(registry) 冗长,个人建议无需过度关注细节(但同时个人感受是反复阅读和 Debug 确实有益于加深理解,看个人时间和精力)。

基于配置类的 BeanDefinition Registry(也就是 BeanFactory),获取配置类,构建和校验配置模型:

  1. BeanDefinition Registry(即 BeanFactory)中查找配置类。
  2. 解析配置类得到配置模型,从模型中读取 BeanDefinitions 注册到 BeanDefinition Registry
  3. 新的 BeanDefinitions 可能有新的配置类,回到 1 再来一遍。重复循环直到不再引入新的配置类。

以本文示例进行说明,静态添加的配置类只有 BeanConfig,假如 BeanConfig 不仅被 Configuration 注解标注,还被 ComponentScan 注解标注,并且刚好 Spring 通过扫描获得并添加了新的配置类,那么新的配置类就需要继续被解析。

应正视配置模型这个概念,它可以理解为配置类到 BeanDefinitions 的中间产物。最初我先入为主,带着解析得到 BeanDefinitions 这样“一阶段”完成的观念,非常不理解 processConfigBeanDefinitions 方法上 Build and validate a configuration model based on the registry of Configuration classes 这句注释。先行强调注意,处理配置类得到 bean 定义分为“两阶段”,解析配置类得到配置模型,从配置模型中读取 bean 定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>();
// 刚开始,获取全部的 BeanDefinitions 作为候选
String[] candidateNames = registry.getBeanDefinitionNames();

for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
// 根据 beanDef 的 attributes 判断是 Full 还是 Lite 的配置类
// 已经处理过的配置类,会在 attributes 中添加标识
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
// 未处理过的候选者,检查是否是配置类。
// configCandidates 的命名让人有些困惑,个人认为这里指代的就是配置类
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}

// Return immediately if no @Configuration classes were found
// 和注释略有不符,配置类的判定没有这么单一,不仅限于 @Configuration 注解的 Full 配置类
if (configCandidates.isEmpty()) {
return;
}

// 根据 attributes 中的 order 排序(来源于 @Order 注解,可能不存在)
Collections.sort(configCandidates, new Comparator<BeanDefinitionHolder>() {
@Override
public int compare(BeanDefinitionHolder bd1, BeanDefinitionHolder bd2) {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
}
});

// 检测应用上下文中是否配置了自定义 bean 名称生成策略
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet && sbr.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) {
// 如果 localBeanNameGenerator 未设置,且 SingletonBeanRegistry 中存在,就获取并使用
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}

// 创建 ConfigurationClassParser,解析每一个配置类(不限于 Full 类型)
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);

// 配置类候选
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates);
// 处理过的配置模型,已经被读取过 Bean 定义
// 个人感觉命名为 alreadyRead 更为准确
Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size());
do {
// 解析
parser.parse(candidates);
// 校验
parser.validate();

// 从 parser 中获取 ConfigurationClass,这就是配置模型(忍不住吐槽一下这个命名和配置类好容易搞混)
Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(parser.getConfigurationClasses());
// 排除已经读取过 Bean 定义的 ConfigurationClass
configClasses.removeAll(alreadyParsed);

// Read the model and create bean definitions based on its content
// 读取模型并根据它的内容创建 BeanDefinitions
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
// 加载(读取并注册) BeanDefinitions
this.reader.loadBeanDefinitions(configClasses);
// 添加到已经读取过的配置模型集合中(上面的 configClasses.removeAll(alreadyParsed) 造成的干扰好大)
alreadyParsed.addAll(configClasses);

// 清空这一轮处理的配置类集合
candidates.clear();
// 通过 registry 中的 BeanDefinitions 数量判断是否有新增的 BeanDefinitions
if (registry.getBeanDefinitionCount() > candidateNames.length) {
// 重新获取全部 BeanDefinitions 作为候选
String[] newCandidateNames = registry.getBeanDefinitionNames();
// 保留旧的候选集合用于快速筛选
Set<String> oldCandidateNames = new HashSet<String>(Arrays.asList(candidateNames));
// 为什么 alreadyParsedClasses 不定义在循环外,需要每次动态地从 alreadyParsed 获取?难道 configurationClass.getMetadata().getClassName() 的结果会变化吗?
// 如果不存在上述情况,直接在添加到 alreadyParsed 时,添加到 alreadyParsedClasses 就好了呀?
Set<String> alreadyParsedClasses = new HashSet<String>();
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) {
if (!sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
}

// 清理 metadataReaderFactory 缓存
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}

判断是否是配置类

checkConfigurationClassCandidate 方法:

  1. 不能 classNamenullBean 定义拥有工厂方法
  2. Configuration 注解标注(全配置类)
  3. ComponentComponentScanImportImportResource 注解标注或者拥有被 Bean 注解标注的方法
  4. 设置 order 用于排序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
String className = beanDef.getBeanClassName();
if (className == null || beanDef.getFactoryMethodName() != null) {
// 如果 className 为 null,或者拥有工厂方法,返回 false
// 举例,被 @Bean 注解的方法返回的 Bean,它的类即使被 @Configuration 注解,也不属于配置类
return false;
}

// 获取 AnnotationMetadata
// 这些分支对应的场景?
AnnotationMetadata metadata;
if (beanDef instanceof AnnotatedBeanDefinition &&
className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
// 可以复用 BeanDefinition 中已经解析过的 metadata
metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
}
else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
// 检查是否存在已经加载的 Class,因为我们可能甚至无法加载该类的类文件
// 创建 metadata 看起来也没干什么事情呀
Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
metadata = new StandardAnnotationMetadata(beanClass, true);
}
else {
// 第二个分支提到的无法加载类文件的情况是指这里吗?
try {
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
metadata = metadataReader.getAnnotationMetadata();
}
catch (IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not find class file for introspecting configuration annotations: " + className, ex);
}
return false;
}
}

if (isFullConfigurationCandidate(metadata)) {
// 属于 Full 配置类,添加 Attribute 标记,标识已处理过
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
else if (isLiteConfigurationCandidate(metadata)) {
// 属于 Lite 配置类,添加 Attribute 标记,标识已处理过
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
return false;
}

// 不管是 Full 还是 Lite 配置类,检查是否被 @Order 注解,如果有则设置到 Attribute,用于排序
Map<String, Object> orderAttributes = metadata.getAnnotationAttributes(Order.class.getName());
if (orderAttributes != null) {
beanDef.setAttribute(ORDER_ATTRIBUTE, orderAttributes.get(AnnotationUtils.VALUE));
}

return true;
}

判断是否属于 Full 配置类

  1. Configuration 注解标注
1
2
3
public static boolean isFullConfigurationCandidate(AnnotationMetadata metadata) {
return metadata.isAnnotated(Configuration.class.getName());
}

判断是否属于 Lite 配置类

  1. ComponentComponentScanImportImportResource 注解标注
  2. 拥有被 Bean 注解标注的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static boolean isLiteConfigurationCandidate(AnnotationMetadata metadata) {
// 接口和注解,直接返回 false
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());
}
catch (Throwable ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex);
}
return false;
}
}

循环处理直至没有新增配置类

循环处理部分的代码有点难阅读。

  • 首先是因为命名比较相似,需要理清各个变量的含义和作用
    • candidateNames 就是普普通通的纯候选者(全部 BeanDefinitions),每次循环在解析完,加载 BeanDefinitions 后可能会新增
    • configCandidatescandidates) 就是符合配置类条件的配置类。虽然命名带 Candidates,其实已经是正牌,并非候选。感觉 configClass 更容易理解,但该变量名另作他用。有新增就要继续循环
    • configClassConfigurationClass 类) 是经过解析的配置模型,不要和配置类搞混了。后面出现过 ConfigurationModel,感觉该命名更加准确
  • 其次是因为对黑盒 parser 的作用不了解,个人经验如果完全将 parser 当作黑盒对待,不了解解析过程、解析的返回结果以及如何处理返回结果,理解循环解析的过程时会有点困难
    • parser.parse(candidates) 解析配置类构建得到配置模型(ConfigurationClass)。以副作用的形式进行处理,传入 ConfigurationClass,返回 ConfigurationClass
    • this.reader.loadBeanDefinitions(configClasses) 从配置模型(ConfigurationClass)中加载 BeanDefinitions

再次提示:正视配置模型的概念,ConfigurationClassParser 使用配置类构建配置模型并校验;ConfigurationClassBeanDefinitionReader 从配置模型中读取 bean 定义。

解析配置类构建配置模型

parser.parse(candidates) 正式进入解析过程,ConfigurationClassParser 负责将配置类转换为配置模型(ConfigurationClass)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public void parse(Set<BeanDefinitionHolder> configCandidates) {
this.deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>();

// 循环依次处理配置类
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof AnnotatedBeanDefinition) {
// 拥有注解的 BeanDefinition
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);
}
}

processDeferredImportSelectors();
}

每次都创建一个新的配置模型 ConfigurationClass,最终处理结果以副作用的形式直接表现在配置模型上。

1
2
3
4
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
// 每次都 new 一个 ConfigurationClass
processConfigurationClass(new ConfigurationClass(metadata, beanName));
}

处理配置模型的方法 processConfigurationClass

  1. 检查配置模型是否曾经处理过
  2. 处理配置模型(递归处理配置类和它的父类)

SourceClass 是一个简单的包装器,无论带注解的源类是如何被加载的,允许以统一的方式处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
// 判断是否跳过
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}

// ConfigurationClass 重写了 equals 和 hashCode 方法
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
// 判断是否已经存在
if (existingClass != null) {
// 检查是否是导入的
if (configClass.isImported()) {
if (existingClass.isImported()) {
// 如果新的旧的 isImported 均为 true,合并 ImportedBy 集合
existingClass.mergeImportedBy(configClass);
}
// Otherwise ignore new imported config class; existing non-imported class overrides it.
return;
}
else {
// 可能找到了一个显式定义的配置类,用于代替导入的,直接移除旧的
this.configurationClasses.remove(configClass);
for (Iterator<ConfigurationClass> it = this.knownSuperclasses.values().iterator(); it.hasNext();) {
if (configClass.equals(it.next())) {
it.remove();
}
}
}
}

// 递归处理配置类和它的父类
SourceClass sourceClass = asSourceClass(configClass);
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);

// 保存处理过的配置模型
this.configurationClasses.put(configClass, configClass);
}

注意 ConfigurationClass 重写了 equalshashCode 方法,metadataclassName 相同代表配置模型也相同。

1
2
3
4
5
6
7
8
public boolean equals(Object other) {
return (this == other || (other instanceof ConfigurationClass &&
getMetadata().getClassName().equals(((ConfigurationClass) other).getMetadata().getClassName())));
}

public int hashCode() {
return getMetadata().getClassName().hashCode();
}

真正处理配置模型的方法,根据注释很容易知道,如果配置类携带了 PropertySourceComponentScanImportImportResourceBean 等注解,就是在这里被处理的。
比如示例中被 Bean 注解标注的方法,configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)) 将它以 BeanMethod 的形式添加到配置模型中。

  1. 先递归的处理成员(嵌套)类
  2. 处理 @PropertySource
  3. 处理 @ComponentScan
  4. 处理 @Import
  5. 处理 @ImportResource
  6. 处理 @Bean使用 ASM 代替 JVM 反射,以获得确定性的声明顺序
  7. 处理接口的默认方法
  8. 检查是否有父类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {

// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass);

// Process any @PropertySource annotations
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
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) {
if (ConfigurationClassUtils.checkConfigurationClassCandidate(
holder.getBeanDefinition(), this.metadataReaderFactory)) {
parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
}
}
}
}

// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), true);

// Process any @ImportResource annotations
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
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.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;
}

读取配置模型,加载 Bean 定义

this.reader.loadBeanDefinitions(configClasses) 读取配置模型的内容,注册 BeanDefinitionsBeanDefinition Registry(也就是 BeanFactory)。

1
2
3
4
5
6
7
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
// 叫 ConfigurationModel 多好啊,ConfigurationClass 真让人容易误解
for (ConfigurationClass configClass : configurationModel) {
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}

处理单独的一个配置模型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

增强配置类

我们在介绍 ConfigurationClassPostProcessor 时提过,它既实现了接口 BeanDefinitionRegistryPostProcessor,也因此同时实现了接口 BeanFactoryPostProcessor。在 invokeBeanFactoryPostProcessors(beanFactory) 阶段,调用 postProcessBeanDefinitionRegistry 方法,成功注册配置类引入的 Bean 后,紧接着会调用 postProcessBeanFactory 方法,增强配置类本身。

ConfigurationClasses 在之前还是指配置模型,这里就又指配置类了。。。真让人头秃。

1
2
3
4
5
6
7
8
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// ...

// 增强配置类
enhanceConfigurationClasses(beanFactory);
// 添加后处理器 ImportAwareBeanPostProcessor
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}

增强所有 Full 类型配置类

  1. 查找所有 Full 类型的配置类
  2. 依次使用 ConfigurationClassEnhancer 增强目标类,成功则替换 BeanClass(不成功的情况是已经增强过)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<String, AbstractBeanDefinition>();
// 获取全部的 BeanDefinitions 检查是否存在全配置类(FullConfigurationClass)
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {
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.isWarnEnabled() && beanFactory.containsSingleton(beanName)) {
logger.warn("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()) {
return;
}
// 通过 CGLib 增强
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
AbstractBeanDefinition beanDef = entry.getValue();
// 如果被 @Configuration 注解的类被代理,则始终代理目标类(proxy target class),在 Attributes 中标记
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
try {
Class<?> configClass = beanDef.resolveBeanClass(this.beanClassLoader);
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Replacing bean definition '%s' existing class '%s' with " +
"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
}
// 如果成功增强,则替换掉 BeanClass
beanDef.setBeanClass(enhancedClass);
}
}
catch (Throwable ex) {
throw new IllegalStateException("Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
}
}
}
  1. 如果增强过则不再处理。这往往代表容器中存在多个 ConfigurationClassPostProcessor,虽然无害,但是建议调整配置
  2. 如果未曾增强过,则创建增强类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public Class<?> enhance(Class<?> configClass, ClassLoader classLoader) {
// 增强过的类都实现了 EnhancedConfiguration,因此可以起到标识作用
if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Ignoring request to enhance %s as it has " +
"already been enhanced. This usually indicates that more than one " +
"ConfigurationClassPostProcessor has been registered (e.g. via " +
"<context:annotation-config>). This is harmless, but you may " +
"want check your configuration and remove one CCPP if possible",
configClass.getName()));
}
return configClass;
}
// 创建增强类
Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
if (logger.isDebugEnabled()) {
logger.debug(String.format("Successfully enhanced %s; enhanced class name is: %s",
configClass.getName(), enhancedClass.getName()));
}
return enhancedClass;
}

创建 CGLib 子类

如果完全不熟悉 CGLib,可以单独查阅一下相关资料,稍作了解。

创建 Enhancer,并设置属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private Enhancer newEnhancer(Class<?> superclass, ClassLoader classLoader) {
Enhancer enhancer = new Enhancer();
// 设置被增强的类为父类
enhancer.setSuperclass(superclass);
// 设置接口,可以用于标识类被增强过
enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
enhancer.setUseFactory(false);
// 设置命名策略,BySpringCGLIB 后缀
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
// 设置生成策略,这里为 CGLib 子类新增一个 $$beanFactory 属性
enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
// 设置 CallbackFilter,用于方法匹配
enhancer.setCallbackFilter(CALLBACK_FILTER);
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
return enhancer;
}
  • 所有因为 Configuration 注解而被增强的配置类,它的 CGLib 子类都实现了这个标记接口,用于检查候选类是否已经增强过,避免重复增强。
  • 该接口继承了 BeanFactoryAware。**创建得到的 CGLib 子类必须能够访问 BeanFactory**,用以在工厂方法交叉调用时获取已经创建的 Bean 而非真正执行。
1
2
public interface EnhancedConfiguration extends BeanFactoryAware {
}

创建子类,并注册静态回调。

1
2
3
4
5
6
private Class<?> createClass(Enhancer enhancer) {
Class<?> subclass = enhancer.createClass();
// 注册静态回调(虽然注释不太理解)
Enhancer.registerStaticCallbacks(subclass, CALLBACKS);
return subclass;
}

CALLBACKSCALLBACK_FILTER$$beanFactory 属性名都是 ConfigurationClassEnhancer 的静态属性。

1
2
3
4
5
6
7
8
9
10
11
class ConfigurationClassEnhancer {
// The callbacks to use. Note that these callbacks must be stateless.
private static final Callback[] CALLBACKS = new Callback[] {
new BeanMethodInterceptor(),
new BeanFactoryAwareMethodInterceptor(),
NoOp.INSTANCE
};
private static final ConditionalCallbackFilter CALLBACK_FILTER = new ConditionalCallbackFilter(CALLBACKS);
private static final String BEAN_FACTORY_FIELD = "$$beanFactory";
// ...
}

匹配回调 ConditionalCallbackFilter

ConditionalCallbackFilter 实现了 CGLibCallbackFilter 接口,accept 方法返回准备使用的 Callback 的索引。匹配规则如下:

  1. 遍历 callbacks,依次判断
    1. 如果 this.callbacks[i] 不是 ConditionalCallback 类型,直接返回。根据 CALLBACKS 的值,这意味着没有匹配到合适的 MethodInterceptor,选择 NoOp.INSTANCE
    2. 如果 this.callbacks[i]ConditionalCallback 类型,使用 isMatch 方法判断是否匹配,匹配成功返回对应索引

Callback 中除了 NoOp.INSTANCE,还有 BeanFactoryAwareMethodInterceptor 用于拦截 setBeanFactory 方法,以及 BeanMethodInterceptor 拦截 @Bean 方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private static class ConditionalCallbackFilter implements CallbackFilter {

private final Callback[] callbacks;

private final Class<?>[] callbackTypes;

public ConditionalCallbackFilter(Callback[] callbacks) {
this.callbacks = callbacks;
this.callbackTypes = new Class<?>[callbacks.length];
for (int i = 0; i < callbacks.length; i++) {
this.callbackTypes[i] = callbacks[i].getClass();
}
}

@Override
public int accept(Method method) {
for (int i = 0; i < this.callbacks.length; i++) {
if (!(this.callbacks[i] instanceof ConditionalCallback) ||
((ConditionalCallback) this.callbacks[i]).isMatch(method)) {
return i;
}
}
throw new IllegalStateException("No callback available for method " + method.getName());
}

public Class<?>[] getCallbackTypes() {
return this.callbackTypes;
}
}

拦截 setBeanFactory 方法

BeanFactoryAwareMethodInterceptor 实现了 MethodInterceptorConditionalCallback 接口。isMatch 匹配到 BeanFactoryAware 接口的 setBeanFactory 方法,则调用 intercept 方法,为 $$beanFactory 属性赋值。$$beanFactoryCGLib 生成的 BeanFactory 类型的属性。这个属性是通过设置 enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader)) 生成的。

这样,当配置类 Bean 被创建时,会因为实现了 BeanFactoryAware,在初始化阶段被调用 setBeanFactory 方法而被拦截。拦截后将获得的 beanFactory 实例保存在 CGlib 生成的属性 $$beanFactory 中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
private static class BeanFactoryAwareMethodInterceptor implements MethodInterceptor, ConditionalCallback {

@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Field field = ReflectionUtils.findField(obj.getClass(), BEAN_FACTORY_FIELD);
Assert.state(field != null, "Unable to find generated BeanFactory field");
// 设置 beanFactory 的值
field.set(obj, args[0]);

// Does the actual (non-CGLIB) superclass implement BeanFactoryAware?
// If so, call its setBeanFactory() method. If not, just exit.
// 如果实际的(non-CGLIB)父类实现了 BeanFactoryAware 接口,调用它的 setBeanFactory() 方法
if (BeanFactoryAware.class.isAssignableFrom(ClassUtils.getUserClass(obj.getClass().getSuperclass()))) {
return proxy.invokeSuper(obj, args);
}
return null;
}

// 根据方法名、参数数量、参数类型、方法所在的类判断
@Override
public boolean isMatch(Method candidateMethod) {
return (candidateMethod.getName().equals("setBeanFactory") &&
candidateMethod.getParameterTypes().length == 1 &&
BeanFactory.class == candidateMethod.getParameterTypes()[0] &&
BeanFactoryAware.class.isAssignableFrom(candidateMethod.getDeclaringClass()));
}
}

生成 $$beanFactory 属性

BeanFactoryAwareGeneratorStrategy 为配置的 CGLib 子类生成一个访问控制符为 public、类型为 BeanFactory、名称为 $$beanFactory 的属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
private static class BeanFactoryAwareGeneratorStrategy extends DefaultGeneratorStrategy {

private final ClassLoader classLoader;

public BeanFactoryAwareGeneratorStrategy(ClassLoader classLoader) {
this.classLoader = classLoader;
}

@Override
protected ClassGenerator transform(ClassGenerator cg) throws Exception {
ClassEmitterTransformer transformer = new ClassEmitterTransformer() {
@Override
public void end_class() {
// 新增一个访问控制符为 public、类型为 BeanFactory、名称为 $$beanFactory 的属性
declare_field(Constants.ACC_PUBLIC, BEAN_FACTORY_FIELD, Type.getType(BeanFactory.class), null);
super.end_class();
}
};
return new TransformingClassGenerator(cg, transformer);
}

// 处理逻辑是清晰的,作用和影响不清楚
@Override
public byte[] generate(ClassGenerator cg) throws Exception {
if (this.classLoader == null) {
return super.generate(cg);
}

Thread currentThread = Thread.currentThread();
ClassLoader threadContextClassLoader;
try {
threadContextClassLoader = currentThread.getContextClassLoader();
}
catch (Throwable ex) {
// Cannot access thread context ClassLoader - falling back...
return super.generate(cg);
}

boolean overrideClassLoader = !this.classLoader.equals(threadContextClassLoader);
if (overrideClassLoader) {
currentThread.setContextClassLoader(this.classLoader);
}
try {
return super.generate(cg);
}
finally {
if (overrideClassLoader) {
// Reset original thread context ClassLoader.
currentThread.setContextClassLoader(threadContextClassLoader);
}
}
}
}

核心:拦截 @Bean 方法

BeanMethodInterceptor 实现了 MethodInterceptorConditionalCallback 接口。isMatch 匹配到被 Bean 注解标注的方法,则调用 intercept 方法。被 Configuration 注解标注的配置类,它定义的被 Bean 注解标注的方法,只会在第一次被调用时真正地执行并创建实例,后续不会再执行的“魔法”就在这里。即使你手动地调用配置类的方法,或是被 Bean 注解标注的方法间互相调用,都是如此。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
MethodProxy cglibMethodProxy) throws Throwable {
// 通过反射,获得 beanFactory 实例
ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
// 获取 beanName,默认是方法名,可以自定义
String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);

// 确定这个 bean 是否属于 scoped-proxy(不了解)
Scope scope = AnnotatedElementUtils.findMergedAnnotation(beanMethod, Scope.class);
if (scope != null && scope.proxyMode() != ScopedProxyMode.NO) {
String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
beanName = scopedBeanName;
}
}

// To handle the case of an inter-bean method reference, we must explicitly check the
// container for already cached instances.

// First, check to see if the requested bean is a FactoryBean. If so, create a subclass
// proxy that intercepts calls to getObject() and returns any cached bean instance.
// This ensures that the semantics of calling a FactoryBean from within @Bean methods
// is the same as that of referring to a FactoryBean within XML. See SPR-6602.
if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
factoryContainsBean(beanFactory, beanName)) {
Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
if (factoryBean instanceof ScopedProxyFactoryBean) {
// Scoped proxy factory beans are a special case and should not be further proxied
}
else {
// It is a candidate FactoryBean - go ahead with enhancement
// 处理 FactoryBean 类型
return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
}
}

// 检查 beanMethod 是不是当前正在被调用的 FactoryMethod
if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
// The factory is calling the bean method in order to instantiate and register the bean
// (i.e. via a getBean() call) -> invoke the super implementation of the method to actually
// create the bean instance.
if (logger.isWarnEnabled() &&
BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
logger.warn(String.format("@Bean method %s.%s is non-static and returns an object " +
"assignable to Spring's BeanFactoryPostProcessor interface. This will " +
"result in a failure to process annotations such as @Autowired, " +
"@Resource and @PostConstruct within the method's declaring " +
"@Configuration class. Add the 'static' modifier to this method to avoid " +
"these container lifecycle issues; see @Bean javadoc for complete details.",
beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName()));
}
// 调用实际的父类方法,创建 Bean 实例
return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
}

// 从 BeanFactory 里获取
return obtainBeanInstanceFromFactory(beanMethod, beanMethodArgs, beanFactory, beanName);
}
  1. isCurrentlyInvokedFactoryMethod(beanMethod) 检查 beanMethod 是不是当前正在被调用的 FactoryMethod
  2. 如果是,则调用实际的父类方法,创建 Bean 实例
  3. 如果不是,则从 BeanFactory 中获取

以本文示例进行说明。

  1. 调用 lisi() 前,设置当前正在调用的 FactoryMethodlisi()
    1. lisi() 调用被拦截后,查询获知当前正在调用的 FactoryMethod 确实是 lisi(),调用父类方法创建
  2. 调用 person() 前,设置当前正在调用的 FactoryMethodperson()
    1. person() 调用被拦截后,查询获知当前正在调用的 FactoryMethod 确实是 person(),调用父类方法创建
    2. 父类方法内调用了 lisi()
      1. lisi() 调用被拦截后,查询获知当前正在调用的 FactoryMethodperson(),从 BeanFactory 中获取
      2. BeanFactory 中获取得到已经创建的 lisi
    3. 继续创建并返回

以上处理的过程是比较清晰简单的,但是当前正在被调用的 FactoryMethod 是什么时候保存的,怎么处理的,还未明朗。

isCurrentlyInvokedFactoryMethod

判断是否是当前正在被调用的 FactoryMethod

1
2
3
4
5
private boolean isCurrentlyInvokedFactoryMethod(Method method) {
Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
return (currentlyInvoked != null && method.getName().equals(currentlyInvoked.getName()) &&
Arrays.equals(method.getParameterTypes(), currentlyInvoked.getParameterTypes()));
}

原理是通过 ThreadLocal 记录正在调用的 FactoryMethod

1
2
3
4
5
6
7
8
9
10
11
12
13
public class SimpleInstantiationStrategy implements InstantiationStrategy {

private static final ThreadLocal<Method> currentlyInvokedFactoryMethod = new ThreadLocal<Method>();

/**
* Return the factory method currently being invoked or {@code null} if none.
* <p>Allows factory method implementations to determine whether the current
* caller is the container itself as opposed to user code.
*/
public static Method getCurrentlyInvokedFactoryMethod() {
return currentlyInvokedFactoryMethod.get();
}
}

这里只是通过 get 获取 currentlyInvokedFactoryMethod 的值,我们还不知道它是在哪更新的。

currentlyInvokedFactoryMethod 的“来龙去脉”

BeanFactory 创建 Bean 实例时,被 Bean 注解标注的方法注册的 Bean 在实例化时是使用工厂方法而不是构造器方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
// ...
if (mbd.getFactoryMethodName() != null) {
// 如果 FactoryMethodName 不为 null,则通过工厂方法实例化
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// ...
}

protected BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, Object[] explicitArgs) {

return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}

BeanFactory 委托给 ConstructorResolver

1
2
3
4
5
6
7
public BeanWrapper instantiateUsingFactoryMethod(
final String beanName, final RootBeanDefinition mbd, final Object[] explicitArgs) {
// ...
beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, factoryBean, factoryMethodToUse, argsToUse);
// ...
}

AbstractAutowireCapableBeanFactoryinstantiationStrategy 类型是 CglibSubclassingInstantiationStrategy,继承自 SimpleInstantiationStrategy

1
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();

SimpleInstantiationStrategyinstantiate 方法在通过反射调用 factoryBean 对应的 method 前后,会处理 currentlyInvokedFactoryMethod 的值。

Bean 注解标注的方法,对应的 Bean 就是一个 FactoryBean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public class SimpleInstantiationStrategy implements InstantiationStrategy {
// ...
@Override
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner,
Object factoryBean, final Method factoryMethod, Object... args) {
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
ReflectionUtils.makeAccessible(factoryMethod);
return null;
}
});
}
else {
ReflectionUtils.makeAccessible(factoryMethod);
}

// 获取之前正在被调用的 FactoryMethod
Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
try {
// 将当前正在被调用的 FactoryMethod 保存
currentlyInvokedFactoryMethod.set(factoryMethod);
// 调用 FactoryMethod
return factoryMethod.invoke(factoryBean, args);
}
finally {
if (priorInvokedFactoryMethod != null) {
// 如果之前正在被调用的 FactoryMethod 不为 null,复原
currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
}
else {
// 否则移除
currentlyInvokedFactoryMethod.remove();
}
}
}
catch (IllegalArgumentException ex) {
throw new BeanInstantiationException(factoryMethod,
"Illegal arguments to factory method '" + factoryMethod.getName() + "'; " +
"args: " + StringUtils.arrayToCommaDelimitedString(args), ex);
}
catch (IllegalAccessException ex) {
throw new BeanInstantiationException(factoryMethod,
"Cannot access factory method '" + factoryMethod.getName() + "'; is it public?", ex);
}
catch (InvocationTargetException ex) {
String msg = "Factory method '" + factoryMethod.getName() + "' threw exception";
if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory &&
((ConfigurableBeanFactory) owner).isCurrentlyInCreation(bd.getFactoryBeanName())) {
msg = "Circular reference involving containing bean '" + bd.getFactoryBeanName() + "' - consider " +
"declaring the factory method as static for independence from its containing instance. " + msg;
}
throw new BeanInstantiationException(factoryMethod, msg, ex.getTargetException());
}
}
}

从 BeanFactory 获取 Bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
private Object obtainBeanInstanceFromFactory(Method beanMethod, Object[] beanMethodArgs,
ConfigurableBeanFactory beanFactory, String beanName) {

// bean 可能已经在创建中
boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName);
try {
if (alreadyInCreation) {
// 暂时添加到 inCreationCheckExclusions,不再检查是否在创建中
beanFactory.setCurrentlyInCreation(beanName, false);
}
boolean useArgs = !ObjectUtils.isEmpty(beanMethodArgs);
if (useArgs && beanFactory.isSingleton(beanName)) {
// 检查参数是否存在 null
for (Object arg : beanMethodArgs) {
if (arg == null) {
useArgs = false;
break;
}
}
}
// 从 beanFactory 获取 Bean
Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
beanFactory.getBean(beanName));
if (beanInstance != null && !ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
String msg = String.format("@Bean method %s.%s called as a bean reference " +
"for type [%s] but overridden by non-compatible bean instance of type [%s].",
beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
beanMethod.getReturnType().getName(), beanInstance.getClass().getName());
try {
BeanDefinition beanDefinition = beanFactory.getMergedBeanDefinition(beanName);
msg += " Overriding bean of same name declared in: " + beanDefinition.getResourceDescription();
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore - simply no detailed message then.
}
throw new IllegalStateException(msg);
}
// 注册依赖关系
Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
if (currentlyInvoked != null) {
String outerBeanName = BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked);
beanFactory.registerDependentBean(beanName, outerBeanName);
}
return beanInstance;
}
finally {
if (alreadyInCreation) {
// 复原状态
beanFactory.setCurrentlyInCreation(beanName, true);
}
}
}

延续自本文的文章: