Spring分析

[toc]

关于Idea中的Maven和Gradle中jdk版本

层次 在哪里设置 主要影响什么 是否直接决定最终编译/运行 JDK 备注
IDEA 项目层 Project Structure -> Project SDK IDEA 的项目模型、代码提示、部分本地运行配置 一般不直接决定 Gradle 项目的最终构建 JDK 更偏 IDE 层
IDEA 语法层 Project Structure -> Language level 编辑器语法检查、补全、部分 IDE 编译设置 一般不直接决定 Gradle 的最终构建 JDK 更偏“能不能写这种语法”
Gradle 进程层(IDEA 外层) Settings -> Gradle -> Gradle JVM IDEA 用哪个 JVM 启动 Gradle、导入项目、执行 Gradle task 会影响,但若配置了 Toolchain,常常不是最终任务 JDK 决定 Gradle 进程跑在哪个 JDK 上
Gradle 进程层(Gradle 内层) gradle.propertiesorg.gradle.java.home 指定这个 Gradle build/Daemon 使用哪个 JDK 运行 会影响,但若配置了 Toolchain,通常也不是最终任务 JDK 相当于强行指定 Gradle 自己跑在哪个 JDK 上
Gradle 任务层 build.gradle 里的 toolchain compileJavatestjavadocJavaExec 等任务实际使用的 JDK 通常最关键 有 Toolchain 时,任务通常按它走
Gradle 兼容层 sourceCompatibility / targetCompatibility / --release 指定源码级别、目标字节码级别、API 兼容级别 会影响编译结果,但不等于指定“Gradle 自己运行的 JDK” 和 Toolchain 不是一回事
Maven 进程层 IDEA 里的 Maven Runner JRE / 系统 JAVA_HOME Maven 这个程序本身跑在哪个 JDK 上 会影响,但若配置了 Maven Toolchains,也未必是最终编译 JDK
Maven 任务层 pom.xml 里的 compiler plugin、toolchains 等 Maven 编译/测试任务实际使用的 JDK 通常是最关键的

Idea中Maven、Gradle项目的三种网络代理方式

方式一:配置Idea(推荐)

image-20260320162810585

方式二:Gradle项目

①全局(不推荐)

配置~/.gradle/gradle.properties文件

1
2
3
4
systemProp.http.proxyHost=127.0.0.1
systemProp.http.proxyPort=7897
systemProp.https.proxyHost=127.0.0.1
systemProp.https.proxyPort=7897

②项目级(推荐)

配置``gradle.properties`文件

1
2
3
4
systemProp.http.proxyHost=127.0.0.1
systemProp.http.proxyPort=7897
systemProp.https.proxyHost=127.0.0.1
systemProp.https.proxyPort=7897

方式三:Maven项目

①全局(不推荐)

配置~/.m2/setting.xml文件

1
2
3
4
5
6
7
8
9
10
11
12
<settings>
<proxies>
<proxy>
<id>local-proxy</id>
<active>true</active>
<protocol>http</protocol>
<host>127.0.0.1</host>
<port>7897</port>
<nonProxyHosts>localhost|127.0.0.1</nonProxyHosts>
</proxy>
</proxies>
</settings>

Spring中的IOC

Bean生命周期概览

BeanFactory 定义了完整的 Bean 生命周期回调顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//初始化阶段:
BeanNameAware.setBeanName()
BeanClassLoaderAware.setBeanClassLoader()
BeanFactoryAware.setBeanFactory()
EnvironmentAware.setEnvironment()
/*
* 各种 Aware 接口回调...
**/
BeanPostProcessor.postProcessBeforeInitialization()
InitializingBean.afterPropertiesSet()
//自定义 init-method
BeanPostProcessor.postProcessAfterInitialization()

//销毁阶段:
DestructionAwareBeanPostProcessor.postProcessBeforeDestruction()
DisposableBean.destroy()
自定义 destroy-method

BeanFactory 接口家族

应用组件的中央注册表,并集中配置应用组件(例如,不再需要单个对象读取属性文件)

分三类:Listable、Configurable、ApplicationContext

BeanFactory
├─ ListableBeanFactory ← 能列举
├─ HierarchicalBeanFactory ← 有层级
│ └─ ConfigurableBeanFactory ← 可配置
│ └─ ConfigurableListableBeanFactory ← 可配置+可列举
└─ ApplicationContext ← 应用级(组合多个接口)
├─ ConfigurableApplicationContext
└─ WebApplicationContext

维度 ListableBeanFactory HierarchicalBeanFactory ConfigurableBeanFactory ApplicationContext
核心职责 批量查询 Bean 支持父子容器层级关系 配置容器本身 企业级功能整合
使用场景 查找某类型的所有 Bean 子容器找不到 Bean 时,会委托给父容器 框架内部配置(类加载器、类型转换、后置处理器等) 实际应用开发
关键方法 getBeansOfType() getParentBeanFactory() addBeanPostProcessor() 继承的所有接口
面向用户 应用开发者 框架开发者 应用开发者
典型实现 DefaultListableBeanFactory AbstractBeanFactory ClassPathXmlApplicationContext
关键参数 allowEagerInit允许热切初始化,(默认false)
1
2
3
4
5
6
7
public interface ApplicationContext extends 
EnvironmentCapable, // 环境配置(profileproperty
ListableBeanFactory, // 批量查询 Bean
HierarchicalBeanFactory, // 父子容器
MessageSource, // 国际化消息
ApplicationEventPublisher, // 事件发布
ResourcePatternResolver // 资源加载

image-20260414171402082

思考

ListableBeanFactory

  • 看完所有方法,理解”批量查询”的概念
  • 重点理解 getBeansOfType() 的两个 boolean 参数
  • 思考:为什么要有 allowEagerInit 这个参数?

ConfigurableBeanFactory

  • 按我上面的分组阅读(类加载器、类型转换、后置处理器等)
  • 重点关注 BeanPostProcessor 相关方法
  • 思考:为什么这是框架内部用的接口?

ApplicationContext

  • 看它继承了哪些接口
  • 逐个查看父接口(MessageSource、ApplicationEventPublisher 等)
  • 对比:ApplicationContext vs BeanFactory 的区别

两个getSingleton

getSingleton(String beanName, boolean allowEarlyReference)

源码理解
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
/**
* Return the (raw) singleton object registered under the given name.
* <p>Checks already instantiated singletons and also allows for an early
* reference to a currently created singleton (resolving a circular reference).
*
* @param beanName the name of the bean to look for
* @param allowEarlyReference whether early references should be created or not
* @return the registered singleton object, or {@code null} if none found
*/
// 理解:从Spring的单例缓存中获取已注册的单例Bean,并支持提前暴露未完全初始化的Bean引用(用于解决循环依赖问题)
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) { // beanName:要查找的Bean名称;allowEarlyReference:是否允许在当前还没有二级缓存对象时,进一步使用三级缓存中的singletonFactory创建early reference
// Quick check for existing instance without full singleton lock.
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { // 一级缓存获取Bean失败,转向二级缓存获取Bean
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) { // 二级缓存未找到,并且允许通过三级缓存获取early reference

if (!this.singletonLock.tryLock()) { // 加锁;避免了多线程并发创建,如获取锁失败,直接返回null
// Avoid early singleton inference outside of original creation thread.
return null;
}
try {
// 理解:下面代码块核心思想是“在并发 + 循环依赖 + AOP 同时存在时,保证单例只会以唯一、稳定、线程安全的方式被提前暴露一次”
// Consistent creation of early reference within full singleton lock.
singletonObject = this.singletonObjects.get(beanName); // ①防止锁前到锁内这段时间发生状态变化 ②保证“加锁后视图”是最新状态;
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); // 从三级缓存获取工厂对象
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject(); // 可能生成 原始对象 或者 AOP代理对象
// Singleton could have been added or removed in the meantime.
if (this.singletonFactories.remove(beanName) != null) { // 失败的情况:①另一个线程已经完成初始化 ②已经通过 addSingleton 放入一级缓存
this.earlySingletonObjects.put(beanName, singletonObject); // 把对象升级到二级缓存
} else {
singletonObject = this.singletonObjects.get(beanName); // 从一级缓存中获取对象
}
}
}
}
} finally {
this.singletonLock.unlock(); // 释放锁
}
}
}
return singletonObject;
}
思考
  1. 为什么在try之前已经有获取锁操作,而try中还要依次从一、二、三级缓存获取对象?

    • 防止锁前到锁内这段时间发生状态变化

    • 保证“加锁后视图”是最新状态

    • 举例:

      • A 进入 getSingleton,准备创建

      • B 在别的路径里已经完成初始化并调用 addSingleton

      • A 现在拿到锁(如果不重新检查一级缓存,A可能会重复创建对象)

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        gantt
        title 相同路径下,A在B释放锁后加锁重新检查缓存
        dateFormat HH:mm:ss
        axisFormat %H:%M:%S

        section 线程A(当前 getSingleton 路径)
        锁外检查未命中 :a1, 00:00:01, 1s
        即将 tryLock :a2, 00:00:02, 1s
        tryLock 成功 :a2, 00:00:07, 1s
        锁内重新检查一二三级缓存 :a3, 00:00:08, 1s
        返回最新可见对象,释放 singletonLock :a4, 00:00:09, 2s

        section 线程B(当前 getSingleton 路径)
        锁外检查未命中 :a1, 00:00:01, 1s
        tryLock 成功 :a2, 00:00:03, 1s
        锁内处理缓存逻辑(初始化对象系列工作) :b2, 00:00:04, 2s
        释放 singletonLock :a5, 00:00:06, 1s
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        gantt
        title 不同路径无锁修改缓存,A加锁后重新检查缓存
        dateFormat HH:mm:ss
        axisFormat %H:%M:%S

        section 线程A(当前 getSingleton 路径)
        锁外检查未命中 :a1, 00:00:01, 1s
        tryLock 成功 :a2, 00:00:02, 1s
        锁内重新检查一二三级缓存 :a3, 00:00:06, 2s
        返回最新可见对象 :a4, 00:00:08, 1s
        释放 singletonLock :a5, 00:00:09, 1s

        section 线程B(不同路径,不加这把锁)
        修改缓存状态 :b1, 00:00:03, 1s
        可能放入一级缓存或调整二/三级缓存 :b2, 00:00:04, 2s
  2. 为什么最后需要判断this.singletonFactories.remove(beanName) != null,为什么从一级缓存中查询,而不一次先查二级再查一级缓存?

    • 获取到的factory可能已经被移除了,可能是另一个线程已经完成初始化了,或者已经通过adSingleton放入一级缓存了

    • 经过情况推理,如果三级缓存中remove失败,不会出现在earlySingletonObjects的情况,所以只能从一级缓存中查询(remove 成功时,二级缓存是当前线程发布early reference的位置;remove失败时,说明当前线程已经不能发布 early reference,因此不再沿着二级缓存这条early reference路线走,而是直接回到一级缓存查最终对象。)

      image-20260507171727869
    • 举例:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      gantt
      title 不同路径无锁修改缓存,A的remove失败并回退到一级缓存
      dateFormat HH:mm:ss
      axisFormat %H:%M:%S

      section 线程A(当前 getSingleton 路径)
      tryLock 成功 :a1, 00:00:01, 1s
      获取 singletonFactory :a2, 00:00:02, 1s
      调用 factory.getObject :a3, 00:00:03, 2s
      remove 失败 :a4, 00:00:05, 1s
      从一级缓存重新获取对象 :a5, 00:00:06, 1s
      释放 singletonLock :a6, 00:00:07, 1s

      section 线程B(不同路径,不加这把锁)
      放入一级缓存 :b1, 00:00:03, 1s
      清理三级缓存 :b2, 00:00:04, 1s
  3. 本代码块中虽然加锁了,但是有一个重点理解:锁只保护这段代码,不能回溯过去,同时也不能阻止别的路径修改缓存;所以锁内逻辑是,防御性确认当前状态是否仍然有效

getSingleton(String beanName, ObjectFactory<?> singletonFactory)

源码理解
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/**
* Return the (raw) singleton object registered under the given name,
* creating and registering a new one if none registered yet.
*
* @param beanName the name of the bean
* @param singletonFactory the ObjectFactory to lazily create the singleton
* with, if necessary
* @return the registered singleton object
*/
@SuppressWarnings("NullAway")
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");

Thread currentThread = Thread.currentThread();
Boolean lockFlag = isCurrentThreadAllowedToHoldSingletonLock(); // true:允许持有 singletonLock,但也允许 tryLock 失败后走宽松 fallback;false:明确不允许持有 singletonLock,强制走宽松 fallback;null:没有特殊指示,走传统行为,必须完整持有 singletonLock
boolean acquireLock = !Boolean.FALSE.equals(lockFlag); // 只有明确返回 FALSE 才完全禁止加锁;只要 lockFlag 是 true 或 null,都会尝试拿 singletonLock
boolean locked = (acquireLock && this.singletonLock.tryLock()); // 尝试非阻塞获取 singletonLock;lock() 会阻塞,tryLock() 失败可以进入宽松模式,减少线程阻塞,提高并发性能

try {
Object singletonObject = this.singletonObjects.get(beanName); // 从一级缓存查是否已经存在单例
if (singletonObject == null) {
if (acquireLock && !locked) { // 当前线程允许尝试拿 singletonLock,但是 tryLock 没拿到
if (Boolean.TRUE.equals(lockFlag)) { // 情况 1:当前线程原本允许拿 singletonLock,但是没抢到。由于它是 true 策略,所以允许它退一步,走宽松创建
// Another thread is busy in a singleton factory callback, potentially blocked.
// Fallback as of 6.2: process given singleton bean outside of singleton lock.
// Thread-safe exposure is still guaranteed, there is just a risk of collisions
// when triggering creation of other beans as dependencies of the current bean.
// 理解:宽松创建
this.lenientCreationLock.lock(); // 加辅助锁,保护两个共享集合:singletonsInLenientCreation、lenientWaitingThreads;不是用来保护整个单例创建过程的,它主要保护这些宽松创建相关的辅助状态
try {
if (logger.isInfoEnabled()) {
Set<String> lockedBeans = new HashSet<>(this.singletonsCurrentlyInCreation);
lockedBeans.removeAll(this.singletonsInLenientCreation);
logger.info("Obtaining singleton bean '" + beanName + "' in thread \"" + currentThread.getName() + "\" while other thread holds singleton " + "lock for other beans " + lockedBeans);
}
this.singletonsInLenientCreation.add(beanName); // 标记这个 bean 正在“宽松创建”,让其他线程知道“当前 bean 可能正在非主锁下创建”
} finally {
this.lenientCreationLock.unlock();
}
} else { // 情况 2:不允许宽松;当前线程没有特殊锁策略,走传统行为。
// No specific locking indication (outside a coordinated bootstrap) and
// singleton lock currently held by some other creation method -> wait.
this.singletonLock.lock(); // 重新尝试获取singletonLock,阻塞等待直至获取成功
locked = true;
// Singleton object might have possibly appeared in the meantime.
singletonObject = this.singletonObjects.get(beanName); // 等拿到锁之后,再查一次一级缓存,因为在它等待锁的过程中,另一个线程可能已经把这个 Bean 创建好了,并放入了一级缓存
if (singletonObject != null) {
return singletonObject;
}
}
}
// 理解:执行到此说明,当前线程明确不允许持有 singletonLock,所以不尝试拿完整锁,直接进入后续创建流程

if (this.singletonsCurrentlyInDestruction) { // 如果容器正在销毁 singleton Bean,就不允许再创建新的 singleton Bean
throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction " + "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}

try {
beforeSingletonCreation(beanName); // 把 beanName 标记为正在创建中
} catch (BeanCurrentlyInCreationException ex) { // 可能有两类情况:1.普通循环依赖或重复创建冲突 2.宽松创建模式下,另一个线程正在创建这个 Bean
this.lenientCreationLock.lock();
try {
while ((singletonObject = this.singletonObjects.get(beanName)) == null) { // 只要一级缓存里还没有这个 Bean,就继续判断是否要等待。
Thread otherThread = this.currentCreationThreads.get(beanName); // 查是谁在创建当前 Bean;currentCreationThreads 不是缓存 Bean 的地方,而是用于并发创建调度和死锁检测的辅助结构
if (otherThread != null && (otherThread == currentThread || checkDependentWaitingThreads(otherThread, currentThread))) { // 检查是否出现等待死锁链:如果发现当前线程和另一个线程之间形成了互相等待,就不能继续等,直接抛异常。
throw ex;
}
if (!this.singletonsInLenientCreation.contains(beanName)) { // 只有当这个 Bean 明确处于宽松创建中,当前线程才适合在这里等待它完成
break;
}
if (otherThread != null) {
this.lenientWaitingThreads.put(currentThread, otherThread); // 记录等待关系:当前线程 currentThread 正在等待 otherThread
}
try {
this.lenientCreationFinished.await(); // 当前线程在条件变量上等待
} catch (InterruptedException ie) {
currentThread.interrupt();
} finally {
if (otherThread != null) {
this.lenientWaitingThreads.remove(currentThread); // 移除等待关系
}
}
}
} finally {
this.lenientCreationLock.unlock();
}
// 理解:等待后有三种结果

// 1. 等到了对象
if (singletonObject != null) { // 如果等待期间,别的线程已经创建完成并放入一级缓存,直接返回。
return singletonObject;
}
// 2. 当前线程已经持有完整锁,但还是冲突
if (locked) { // 如果当前线程本来已经持有 singletonLock,但仍然遇到 BeanCurrentlyInCreationException,说明这个问题不是普通等待能解决的,直接抛异常。
throw ex;
}
// 3. 当前线程之前没有完整锁,尝试 late locking
// Try late locking for waiting on specific bean to be finished.
this.singletonLock.lock(); // 前面没拿完整锁,现在为了等待和确认这个特定 Bean 的最终状态,再补拿一次完整锁。
locked = true;
// Lock-created singleton object should have appeared in the meantime.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject != null) {
return singletonObject;
}
beforeSingletonCreation(beanName); // 如果还没有目标Bean,重新尝试标记创建中
}

// 理解:真正创建 Bean
boolean newSingleton = false;
boolean recordSuppressedExceptions = (locked && this.suppressedExceptions == null);
if (recordSuppressedExceptions) { // 如果当前线程持有完整锁,并且还没有异常记录集合,就创建一个
this.suppressedExceptions = new LinkedHashSet<>(); // 为了记录创建过程中的相关异常,比如临时的循环依赖解析异常
}
try {
// Leniently created singleton object could have appeared in the meantime.
singletonObject = this.singletonObjects.get(beanName); // 宽松创建模式下,可能在此期间别的线程已经把对象创建好了,所以需要查一次一级缓存
if (singletonObject == null) {
this.currentCreationThreads.put(beanName, currentThread); // 记录 beanName 当前由 currentThread 创建
try {
singletonObject = singletonFactory.getObject(); // 实际创建 Bean
} finally {
this.currentCreationThreads.remove(beanName);
}
newSingleton = true; // 表示这是当前线程新创建出来的单例
}
} catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
// 理解:singletonFactory.getObject() 创建 Bean过程中,目标 singleton 可能已经被其他线程或其他创建路径放进了 singletonObjects 一级缓存
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
} catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
} finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName); // 清除创建中标记,把 beanName 从正在创建集合中移除
}

// 理解:创建成功后注册到一级缓存
if (newSingleton) {
try {
addSingleton(beanName, singletonObject); // 把对象放入一级缓存,并清理早期暴露相关缓存:放入 singletonObjects、移除 singletonFactories、移除 earlySingletonObjects、记录 registeredSingletons
} catch (IllegalStateException ex) {
// Leniently accept same instance if implicitly appeared.
Object object = this.singletonObjects.get(beanName);
if (singletonObject != object) {
throw ex;
}
}
}
}
return singletonObject;
} finally {
if (locked) {
this.singletonLock.unlock(); // 如果持有 singletonLock,就释放
}
this.lenientCreationLock.lock();
try {
this.singletonsInLenientCreation.remove(beanName); // 如果这个 Bean 之前被加入了宽松创建集合,这里把它移除
// 理解:当前线程创建结束了,所有可能等着它的线程都应该被唤醒,重新检查一级缓存或状态
this.lenientWaitingThreads.entrySet().removeIf(entry -> entry.getValue() == currentThread);
this.lenientCreationFinished.signalAll();
} finally {
this.lenientCreationLock.unlock();
}
}
}

思考
  1. singletonLock是什么锁?
    • 是某个BeanFactory内部用于保护singleton注册表的公共锁,可以近似理解为“一个容器一把单例锁”,不是单个Bean的锁
  2. isCurrentThreadAllowedToHoldSingletonLock()返回值三种情况处理
    • true:允许持有 singletonLock,但也允许 tryLock 失败后走宽松 fallback
    • false:明确不允许持有 singletonLock,强制走宽松 fallback
    • null:没有特殊指示,走传统行为,必须完整持有 singletonLock

获取Bean:AbstractBeanFactory.doGetBean()

涉及类

image-20260512171433413

流程图

ioc-doGetBean().drawio

源码理解

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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/**
* Return an instance, which may be shared or independent, of the specified bean.
* @param name the name of the bean to retrieve
* @param requiredType the required type of the bean to retrieve
* @param args arguments to use when creating a bean instance using explicit arguments
* (only applied when creating a new instance as opposed to retrieving an existing one)
* @param typeCheckOnly whether the instance is obtained for a type check,
* not for actual use
* @return an instance of the bean
* @throws BeansException if the bean could not be created
*/
// 理解:这是 Spring 获取(或创建)Bean 的总调度方法,负责处理缓存、作用域、依赖关系、循环依赖、父容器委托、类型适配等所有核心流程。​
@SuppressWarnings("unchecked")
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {

String beanName = transformedBeanName(name); // ①处理别名 ②去掉 & 前缀(FactoryBean专用)
Object beanInstance;

// 理解:如果当前 Bean 已经能从单例缓存中拿到,并且本次 getBean 没有显式传入创建参数,那么就直接复用缓存中的单例对象
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName); // 去一、二、三级缓存中查寻(默认在二级缓存中也查不到时,可以通过三级缓存创建早期引用,同时放进二级缓存中)
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null); // 如果是普通Bean,直接返回;如果是FactoryBean,判断要拿的是FactoryBean自身,还是想拿产品对象
}

else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) { // 如果是prototype类型,并且已经在创建中,则报异常(prototype类型的bean第一次创建时不报异常)
throw new BeanCurrentlyInCreationException(beanName);
}

// 理解:父容器委托机制(当前容器查询失败,交给父容器再查询)
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name); // 将name还原成原始的Bean信息,因为name可能是”&、别名、普通Bean名称“三个的任意组合;注意:由于”&别名“情况,所以不能直接用transformedBeanName(name)
if (parentBeanFactory instanceof AbstractBeanFactory abf) { // 如果父容器也是 AbstractBeanFactory 类型,那么可以直接调用父容器的 doGetBean()
return abf.doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) { // 父容器不是 AbstractBeanFactory,那就不能调用 doGetBean(),只能调用 BeanFactory 接口暴露出来的方法。父容器会用这些参数去创建 Bean。
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) { // 指定了返回类型,调用父容器的getBean(),根据名称和期望类型从父容器获取 Bean
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else { // 如果既没有 args,也没有 requiredType,这是最普通的 getBean 调用
return (T) parentBeanFactory.getBean(nameToLookup);
}
}

// 理解:不需要委托给父容器,在当前容器中即可处理
if (!typeCheckOnly) {
markBeanAsCreated(beanName); // 标记 Bean 已进入创建阶段;在真正创建 Bean 之前,冻结该 Bean 的元数据,并确保使用的是最终一致的合并后 BeanDefinition
}

// 理解:StartupStep beanCreation后做的事情见下述“思考3”
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate") // 理解:Spring 5.3+ 引入的应用启动性能监控机制
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // 合并 BeanDefinition;如果不合并,创建时要层层查找父 definition;合并后的definition会缓存到mergedBeanDefinitions
checkMergedBeanDefinition(mbd, beanName, args); // 检查是否抽象、合法、允许创建

// 理解:确保被当前Bean依赖的所有Bean都已经实例化完成了
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) { // 有“depends-on”级别的循环依赖则报异常
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName); // 维护两张依赖图关系:dependentBeanMap、dependenciesForBeanMap二者作用详见“思考5”
try {
getBean(dep); // 递归调用 doGetBean,可能触发:单例创建、循环依赖逻辑、AOP、注入
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
catch (BeanCreationException ex) {
if (requiredType != null) {
// Wrap exception with current bean metadata but only if specifically
// requested (indicated by required type), not for depends-on cascades.
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Failed to initialize dependency '" + .getBeanName() + "' of " + requiredType.getSimpleName() + " bean '" + beanName + "': " + ex.getMessage(), ex);
}
throw ex;
}
}
}

// 理解:创建实例类型1——单例
// Create bean instance.
if (mbd.isSingleton()) {
// 在getSingleton方法中,通过调用传入的参数ObjectFactory.createBean()完成真正的Bean创建过程
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args); // 实际创建Bean的位置
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName); // 防止创建失败后留下半成品状态;singleton 分支的失败处理比 prototype 更复杂,因为 singleton 涉及全局缓存
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); // 为了处理 FactoryBean:普通Bean:直接返回sharedInstance、getBean("xxx") :返回FactoryBean生产的对象、getBean("&xxx") :返回 FactoryBean 本身
}

// 理解:创建实例类型2——原型
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName); // 虽然 prototype 不进 singleton 缓存,但 Spring 仍然要记录,为了检测 prototype 创建中的循环依赖
prototypeInstance = createBean(beanName, mbd, args); // 实际创建Bean的位置
}
finally {
afterPrototypeCreation(beanName); // 清除标记
}
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); // prototype 创建完成后也要处理 FactoryBean
}

// 理解:创建实例类型3——自定义Scope分支:交给Scope对象管理
else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName); // 从 Spring 容器维护的 scopes 的 Map 中,根据 scopeName 获取对应的 Scope 实现对象
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
// 不是直接调用 createBean();Spring 把“如果需要创建对象,应该怎么创建”的回调传给 Scope,由 Scope 决定要不要调用它
// 在当前 scope 范围内获取 beanName 对应的对象。如果当前 scope 中已经有,就直接返回;如果没有,就调用 ObjectFactory 创建一个,再保存到当前 scope 中。
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName); // 创建标记,用于检测循环创建问题
try {
return createBean(beanName, mbd, args); // 实际创建Bean的位置
}
finally {
afterPrototypeCreation(beanName); // 清除创建中标记
}
});
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); // 自定义 Scope 的 Bean 创建完成后也要处理 FactoryBean
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex); // 当前 scope 没有激活,所以无法获取这个 Bean。
}
}
}
catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString()); // 给 StartupStep 打异常标签
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName); // 不是销毁 Bean 本身,而是清理 doGetBean 层面记录的创建状态;Spring 在真正创建 Bean 前,通常会把当前 beanName 标记为已经开始创建。如果创建成功,这个标记可以保留,表示这个 Bean 已经经历过创建流程;但如果创建失败,就不能继续保留这个状态。
throw ex;
}
finally {
beanCreation.end(); // 结束启动性能埋点
if (!isCacheBeanMetadata()) { // 根据配置决定是否清理合并后的 BeanDefinition;Spring 默认通常会缓存这些元数据,因为缓存后性能更好
clearMergedBeanDefinition(beanName); // 清理掉合并后的 BeanDefinition 缓存
}
}
}

// // 创建成功后进行类型适配:
// 1.如果 requiredType 为空,直接返回 beanInstance;
// 2.如果 beanInstance 本身就是 requiredType 类型,直接返回;
// 3.如果可以通过 TypeConverter 转换,则尝试转换;
// 4.如果不能转换,抛 BeanNotOfRequiredTypeException
return adaptBeanInstance(name, beanInstance, requiredType); // 可能是:普通 Bean 实例、AOP 代理对象、FactoryBean 生产的对象、request/session scope 返回的对象
}

思考

  1. 为什么单例能解决循环依赖,而prototype不能?

    • 因为点哪里可以提前暴漏early referenceprototype每次都是新对象,没有缓存支持
  2. 为什么在父容器委托机制中,委托时会多出几种获取Bean的方式,比如根据args创建Bean、根据期望类型获取Bean

    • 当前容器自己处理时,看起来不需要区分 argsrequiredType,是因为当前已经在 doGetBean(...) 这个统一入口里了;在当前容器内部,所有 getBean 调用最终都会汇总到同一个方法,所以当前容器继续往下执行时,不需要再区分调用者最初是:getBean(name)getBean(name, requiredType)getBean(name, args)
    • 但委托给父容器时,父容器未必暴露 doGetBean(...),所以只能根据参数情况选择不同的 getBean(...) 重载方法。
  3. StartupStep beanCreation后紧接的代码块做了什么?

    • 记录性能埋点
    • 合并 BeanDefinition
    • 检查合法性
    • 处理 dependsOn
    • 根据 scope 选择创建策略
    • 单例使用三级缓存支持循环依赖
    • 执行完整生命周期(createBean)
    • 处理 AOP 代理
    • 清理异常状态
    • 类型适配并返回
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    flowchart LR
    A[1. 记录性能埋点] --> B[2. 合并 BeanDefinition]
    B --> C[3. 检查合法性]
    C --> D[4. 处理 dependsOn]
    D --> E[5. 根据 scope 选择创建策略]
    E --> F[6. 单例使用三级缓存支持循环依赖]
    F --> G[7. 执行完整生命周期 createBean]
    G --> H[8. 处理 AOP 代理]
    H --> I[9. 清理异常状态]
    I --> J[10. 类型适配并返回]

    classDef process fill:#EAF3FF,stroke:#2F80ED,stroke-width:1.5px,color:#1B365D,rx:8,ry:8;
    classDef key fill:#F3E8FF,stroke:#8B5CF6,stroke-width:1.5px,color:#3B0764,rx:8,ry:8;
    classDef final fill:#E8F5E9,stroke:#43A047,stroke-width:1.5px,color:#1B5E20,rx:8,ry:8;

    class A,B,C,D,E,I process;
    class F,G,H key;
    class J final;
  4. Spring不是解决了循环依赖问题吗?为什么后面还会报循环依赖的异常?

    • Spring 解决的是“属性注入级别的循环依赖”(@Autowired之类的),使用三级缓存解决,因为三级缓存解决的是:✅ “对象已经实例化,但属性还没注入完成”
    • ❌ 但不允许“depends-on 级别的循环依赖”(@DependsOn("b")之类的),而depends-on的语义是:✅ “当前Bean必须等依赖Bean完全初始化完成”
    • Spring可以解决的循环依赖有边界:
      • 可以解决:
        • 单例 + 非构造器 + 属性注入
      • 不能解决:
        • ❌ 构造器循环
        • ❌ prototype 循环、
        • ❌ depends-on 循环
  5. dependentBeanMapdependenciesForBeanMap两个作用对比

    • Map 作用 主要用途
      dependentBeanMap 从“被依赖者”找“依赖者” ✅ 销毁顺序(Spring 销毁单例时是逆序销毁) ✅ 循环检测 ✅ 查找“谁依赖我”
      dependenciesForBeanMap 从“依赖者”找“被依赖者” ✅ 销毁时删除边 ✅ 查找“我依赖谁” ✅ 图一致性维护
  6. 自定义Scope有什么特殊性?

    • 自定义 scope 的语义不是 Spring 单例池能直接决定的

    • 比如:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      request scope:
      同一次 HTTP 请求内复用;
      不同请求创建不同对象;
      request scope 对象应该存在 request attributes 中。

      session scope:
      同一个 Session 内复用;
      不同 Session 创建不同对象;
      session scope 对象应该存在 session attributes 中。
  7. Spring维护的scopesMap中会有啥?

    • request -> RequestScope
    • session -> SessionScope
    • application -> ServletContextScope
    • websocket -> WebSocketScope
  8. 自定义Scope明明不是 prototype,为什么调用beforePrototypeCreation

    • 对于 Spring 单例池来说,自定义scope Bean也不是 singleton
    • 它没有 singleton 那套创建中标记和三级缓存机制,它不放在singletonObjects,也不走getSingleton(beanName, ObjectFactory)
    • 因此 Spring 借用 prototype 的创建标记机制,记录当前线程正在创建这个非 singleton Bean。主要用于检测循环创建问题。
  9. 创建成功后进行类型适配,类型是谁指定的?

    • 用户显式指定,比如:UserService userService = applicationContext.getBean("userService", UserService.class);
    • Spring内部推断,比如:@Autowired private UserService userService;

创建Bean:AbstractAutowireCapableBeanFactory.doCreateBean()

涉及类

image-20260415182920967

流程图

ioc-doCreateBean()

源码理解

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
/**
* Actually create the specified bean. Pre-creation processing has already happened
* at this point, for example, checking {@code postProcessBeforeInstantiation} callbacks.
* <p>Differentiates between default bean instantiation, use of a
* factory method, and autowiring a constructor.
* @param beanName the name of the bean
* @param mbd the merged bean definition for the bean
* @param args explicit arguments to use for constructor or factory method invocation
* @return a new instance of the bean
* @throws BeanCreationException if the bean could not be created
* @see #instantiateBean
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
*/
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {

// Instantiate the bean.
// 理解:获取Bean的包装类;这一段本质上是为了兼容 FactoryBean 类的对象能和普通 Bean 创建流程复用同一套创建逻辑
BeanWrapper instanceWrapper = null; // 逻辑:BeanWrapper 是 Bean 实例的元数据包装器
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); // 理解:仅实现了 FactoryBean 接口的 Bean,且单例,且尚未走完创建过程,才会在后续代码中临时放在 FactoryBeanInstanceCache 中;
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args); // 理解:factoryBeanInstanceCache 未获取到的 FactoryBean 和普通单例 Bean 可以走
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}

// Allow post-processors to modify the merged bean definition.
// 理解:完善BeanDefinition
synchronized (mbd.postProcessingLock) { // 理解:每个BeanDefinition有独立的锁;
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); // 理解:修改合并后的 BeanDefinition,即调用所有 MergedBeanDefinitionPostProcessor 的实现,包括@Autowired、@Value、@PostConstruct 等注解的元数据处理;
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.markAsPostProcessed(); // 理解:进度标记
}
}

// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 理解:提前暴露单例 Bean(用于解决循环依赖)
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && // 理解:单例 + 允许循环引用(默认true)+
isSingletonCurrentlyInCreation(beanName)); // 理解:是否检测到同一个 beanName 已经在创建中了,说明可能有其他 Bean 依赖它
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); // 理解:提前暴露,将 Bean 的工厂函数添加到 singletonFactories 第三级缓存;传的函数实参,本质是new一个对象ObjectFactory;这里暴露的是原始对象,可能后续会被 AOP 代理包装;这里暴露的是原始对象
}

// Initialize the bean instance.
// 理解:正式初始化实例,注意之前执行过 bean = instanceWrapper.getWrappedInstance();
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper); // 理解:按照BeanDefinition进行属性填充,如注入依赖的 Bean、设置属性值;会调用 getBean 方法;如有依赖,触发其他 Bean 的创建;这里注入的是普通 Bean 或者 FactoryBean 自身
exposedObject = initializeBean(beanName, exposedObject, mbd); // 理解:初始化,依次执行Aware接口回调、BeanPostPorcessor.postProcessBeforeInitialization()、@PostConstruct和InitializingBean.afterPropertiesSet()和自定义 init-method、BeanPostProcessor.postProcessAfterInitialization();注意:返回的 exposedObject 可能是代理对象(AOP在此阶段创建),此时 exposedObject != bean
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException bce && beanName.equals(bce.getBeanName())) {
throw bce;
}
else {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, ex.getMessage(), ex);
}
}

// 理解:循环依赖验证
if (earlySingletonExposure) { // 理解:之前允许提前暴露过了
Object earlySingletonReference = getSingleton(beanName, false); // 理解:获取二级缓存中的早期引用,可能不存在;依次去一级、二级、三级查询,同时 false 控制不去三级缓存查询,又因为本 Bean 尚未创建结束,所以一级缓存中不存在本 Bean
if (earlySingletonReference != null) { // 理解:非空说明,该 Bean 不只是出现在了三级缓存的工厂,而是被别人去过早期引用,且这个早期引用对象放进了二级缓存,很大概率但不一定是循环依赖(反例:某刻 A 在创建中,在创建 X 的过程中,某个后处理器、类型匹配逻辑,或者某段框架代码,过早地去按类型查找 A)
if (exposedObject == bean) { // 理解:初始化完成后,最终对象 exposedObject 仍然就是原始对象 bean
exposedObject = earlySingletonReference; // 理解:之前三级缓存中被调用过 getEarlyBeanReference,返回的 earlySingletonReference 可能是二级缓存中的提前代理对象,Srping 需要保证一致性
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { // 理解:if 判断中传递过来的 exposedObject 是代理对象 && 是否允许”别人注入的是原始对象,但最终容器里保存的是包装对象“ && 有其他 Bean 依赖当前 Bean
String[] dependentBeans = getDependentBeans(beanName); // 理解:获取所有依赖的 Bean
Set<String> actualDependentBeans = CollectionUtils.newLinkedHashSet(dependentBeans.length); // 理解:new 一个同等长度的 Set 集合
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { // 理解:筛选出真正依赖当前 Bean,即已经进入了 alreadyCreated 这个“正式创建过”的集合中的 Bean;过滤掉只是为了类型检查、候选匹配等临时目的被创建出来的单例 Bean
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) { // 理解:出现问题”初始化完成后,exposedObject 变成了包装对象,而其他 Bean 可能已经注入了这个 Bean 二级缓存中的对象,导致系统中出现了同一个 Bean 的两个版本“
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}

// Register bean as disposable.
// 理解:注册销毁
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd); // 理解:bean 注册销毁,而不是用 exposedObject,因为销毁管理针对的是 BeanDefinition 对应的原始生命周期主体;而 exposedObject 只是初始化后最终对外暴露的版本,可能是代理或包装对象
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}

return exposedObject;
}

思考

  1. 为什么 FactoryBeandoCreateBean() 中一开始还要尝试从缓存中获取 instanceWrapper
  • 正式进入 doCreateBean() 之前,常常就需要围绕 FactoryBean 本身 做一些额外分析,例如:推断它的类型、决定构造器选择、判断后续产品对象相关语义,因此,Spring 可能会提前为 FactoryBean 本身 创建并缓存一个 BeanWrapper,等真正进入 doCreateBean() 时直接复用。
  • 这里名字虽然叫factoryBeanInstanceCache,但它缓存的是FactoryBean 本身的 BeanWrapper
  • 普通Bean通常直接实例化就够了,流程简单,没必要专门走一套额外缓存。
  1. 在属性填充时,Spring使用BeanWrapper而不是直接传递Bean实例的设计原因
  • 装饰器模式:BeanWrapper包装Bean实例,增强功能
  • 反射:直接Bean无类型转换,而BeanWrapper内置PropertyEditor体系
  • 嵌套属性:直接Bean无法处理,而BeanWrapper支持getPropertyValue("user.name")
  • 元数据:BeanWrapper保留属性编辑器的注册信息
  1. 二级缓存在什么时候加入Bean的早期引用的
  • 在获取引用时,依次从一级、二级、三级中查找,如果查找到了三级缓存,并且找到了,则会在找到后将其加入二级缓存,从三级缓存移除(详见上面getSingleton()
  1. exposedObject = earlySingletonReference;如果是代理状态,不应该是同一个代理对象吗
  • 二级缓存中的早期引用 earlySingletonReference 有可能在更早阶段就已经被“提前代理”了,而 initializeBean(...) 之后的 exposedObject 却仍然只是原始对象。
    • 也有可能这两个都是代理对象,但是不同的代理对象,并不同步,exposedObject 来自正常初始化后的最终结果,而 earlySingletonReference 来自二级缓存中的早期引用,它可能早在三级缓存工厂被调用时就已经被提前代理了。正因为这两个阶段可能不一致
  1. 如果当前 Bean 是 FactoryBean,注册销毁时注册的是谁
  • FactoryBean 本身,因为当前 doCreateBean() 创建和初始化的对象就是 FactoryBean 自己,而 FactoryBean#getObject() 生产出来的产品对象,不是在这一步注册销毁的。产品对象的销毁要看后续获取与缓存管理逻辑,尤其是单例产品对象时,会在 FactoryBean 相关分支中处理。
  1. doCreateBean()FactoryBean 的处理是否只针对 FactoryBean 自身?如果是,为什么分析这个方法时还要特别关注 FactoryBean#getObject()
  • 单看 doCreateBean(),这个方法负责的是当前 BeanDefinition 对应实例的创建、属性填充、初始化、循环依赖处理和销毁注册;如果这个实例是 FactoryBean,那这里处理的就是 FactoryBean 本体,不是它的产品对象。

  • 之所以还要特别注意 getObject(),是因为doGetBean 还会通过 getObjectForBeanInstance() 等逻辑判断:最终返回给调用方的是 FactoryBean 本身,还是它通过 getObject() 生产的产品对象。

循环依赖,三级缓存解决

完整启动流程ApplicationContext.refresh()

Spring中的AOP

Spring中的MVC

SpringBoot中的自动配置

Contents
  1. 1. 关于Idea中的Maven和Gradle中jdk版本
  2. 2. Idea中Maven、Gradle项目的三种网络代理方式
    1. 2.1. 方式一:配置Idea(推荐)
    2. 2.2. 方式二:Gradle项目
    3. 2.3. 方式三:Maven项目
  3. 3. Spring中的IOC
    1. 3.1. Bean生命周期概览
    2. 3.2. BeanFactory 接口家族
    3. 3.3. 两个getSingleton
      1. 3.3.1. getSingleton(String beanName, boolean allowEarlyReference)
        1. 3.3.1.1. 源码理解
        2. 3.3.1.2. 思考
      2. 3.3.2. getSingleton(String beanName, ObjectFactory<?> singletonFactory)
        1. 3.3.2.1. 源码理解
        2. 3.3.2.2. 思考
    4. 3.4. 获取Bean:AbstractBeanFactory.doGetBean()
      1. 3.4.1. 涉及类
      2. 3.4.2. 流程图
      3. 3.4.3. 源码理解
      4. 3.4.4. 思考
    5. 3.5. 创建Bean:AbstractAutowireCapableBeanFactory.doCreateBean()
      1. 3.5.1. 涉及类
      2. 3.5.2. 流程图
      3. 3.5.3. 源码理解
      4. 3.5.4. 思考
    6. 3.6. 循环依赖,三级缓存解决
    7. 3.7. 完整启动流程ApplicationContext.refresh()
  4. 4. Spring中的AOP
  5. 5. Spring中的MVC
  6. 6. SpringBoot中的自动配置
|