总体的类图

spring-Ioc
spring-ioc-hiarachy
BeanFactory的继承树
工厂和注册表之间的关系
工厂与上下文

Bean 工厂提供 IOC 基本功能,Context 是全功能的 BeanFactory,是应用程序的全部上下文。

扩展点和生命周期钩子

Spring的扩展点.xmind
Spring的扩展点
spring-bean-lifecycle-1.png
spring-bean-lifecycle-2.png

加载顺序:

  1. 获取工厂
  2. 准备工厂
  3. 后处理工厂
  4. InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation,返回 object。
  5. 构造器
  6. InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation,返回布尔值。
  7. populateBean(注入 @Autowired,类内第一个方法),实际上调用的是 InstantiationAwareBeanPostProcessor.postProcessProperties
  8. InitializingBean:
    • 各类 aware 方法注入
    • BeanPostProcessor.postProcessBeforeInitialization 的后处理器(@PostConsstruct)
    • afterPropertiesSet,类内第二个方法
    • init 方法,类内第三个方法
    • BeanPostProcessor.postProcessAfterInitialization
    • InstantiationAwareBeanPostProcessor.postProcessAfterInitialization,比较容易被忽略,它继承了父类的方法

关闭顺序:ContextClosedEvent -> @PreDestroy -> DisposableBean -> destroy-method

Bean生命周期

容易被混淆的是实例化和初始化,而且很多人没有意识到,这两者之间还存在一个明确,但经常被忘记的“属性赋值”阶段。

关闭的生命周期钩子

基本的原则是:

make bean ready -> start working -> stop working -> destroy bean

其中线程的协调在中间两步。

对应在一般实现里扩展点的使用应该是:

  1. make bean ready:@PostConstruct 及以前的钩子
  2. start working 的钩子是:ContextRefreshedEvent
  3. stop working 的钩子是:ConxtextClosedEvent
  4. destroy bean 的钩子是:@Predestroy 及以后的钩子

JVM 的裸钩子

用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static void main(String[] args) {
// 注册关闭钩子应该写在主线程开始 working 以前
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
while (true) {
try {
Thread.sleep(1000L);
log.info("关闭钩子:又活了一个周期");
} catch (Exception ex) {
log.info("interrupted: ", ex);
}
}
}));
while (true) {
try {
Thread.sleep(1000L);
log.info("又活了一个周期");
} catch (Exception ex) {
log.info("interrupted: ", ex);
// break;
}
}
}

在运行时,不断循环打印15:06:04.856 [main] INFO com.magicliang.TestHook - 又活了一个周期,使用普通的 kill,得到交替的输入:

15:06:06.206 [Thread-1] INFO
com.magicliang.TestHook - 关闭钩子:又活了一个周期
15:06:06.861 [main] INFO com.magicliang.TestHook

  • 又活了一个周期

这证明几件事:

  1. kill 不会触发 interrupt。我们需要显式地把线程池的shutdown和 JVM 的 shutdown hook 关联起来。
  2. 主线程和关闭钩子可以无限同步运行,阻塞 jvm 的关闭,所以它们自身应该是可以最终终止的流程。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    public static void main(String[] args) {
AtomicBoolean atomicBoolean = new AtomicBoolean(true);
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
atomicBoolean.set(false);
while (true) {
try {
Thread.sleep(1000L);
log.info("关闭钩子:又活了一个周期");
} catch (Exception ex) {
log.info("interrupted: ", ex);
}
}
}));
while (atomicBoolean.get()) {
try {
Thread.sleep(1000L);
log.info("又活了一个周期");
} catch (Exception ex) {
log.info("interrupted: ", ex);
// break;
}
}
}

输出:

15:15:36.893 [main] INFO com.magicliang.TestHook -
又活了一个周期 15:15:37.896 [main] INFO
com.magicliang.TestHook - 又活了一个周期 15:15:38.901
[main] INFO com.magicliang.TestHook - 又活了一个周期
15:15:39.904 [main] INFO com.magicliang.TestHook -
又活了一个周期 15:15:40.572 [Thread-1] INFO
com.magicliang.TestHook - 关闭钩子:又活了一个周期 15:15:41.575
[Thread-1] INFO com.magicliang.TestHook -
关闭钩子:又活了一个周期

因为关闭钩子还在不断执行,即使工作线程关闭,JVM 会一直不关闭。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    public static void main(String[] args) {
AtomicBoolean atomicBoolean = new AtomicBoolean(true);
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
log.info("我只活一次");
}));
while (true) {
try {
Thread.sleep(1000L);
log.info("又活了一个周期");
} catch (Exception ex) {
log.info("interrupted: ", ex);
// break;
}
}
}

特别地,如果使用平凡的 kill 命令,是 SIGTERM 退出:

15:26:53.515 [main] INFO leads.system.com.magicliang.TestHook -
又活了一个周期 15:26:54.520 [main] INFO
leads.system.SpringApplicationMultiStartup - 又活了一个周期 15:26:54.987
[Thread-1] INFO leads.system.SpringApplicationMultiStartup - 我只活一次

进程已结束,退出代码143 (interrupted by signal 15: SIGTERM)

如果使用 idea 的正方形按钮退出,是 SIGINT 退出:

15:28:10.508 [main] INFO leads.system.SpringApplicationMultiStartup -
又活了一个周期 15:28:11.518 [main] INFO
leads.system.SpringApplicationMultiStartup - 又活了一个周期 15:28:12.521
[main] INFO leads.system.SpringApplicationMultiStartup - 又活了一个周期
15:28:13.266 [Thread-1] INFO
leads.system.SpringApplicationMultiStartup - 我只活一次

进程已结束,退出代码130 (interrupted by signal 2: SIGINT)

最终结论,主线程不会导致 JVM 无法退出,关闭钩子会。

这个实现机制见 System.exit

Spring 的钩子

在 AbstractApplicationContext 中,注册 JVM 的钩子:

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
// AbstractApplicationContext 里的钩子,所有的 ConfigurableApplicationContext(作为 SPI 的主接口) 如果可以 cast 成 AbstractApplicationContext

// 利用了 JVM 钩子来挂载自身的框架函数,但这个钩子不常被调用。从一般教程来看,需要持有特定 context 的代码主动调用,看起来不会被生命周期钩子调用
@Override
public void registerShutdownHook() {
if (this.shutdownHook == null) {
// No shutdown hook registered yet.
this.shutdownHook = new Thread(SHUTDOWN_HOOK_THREAD_NAME) {
@Override
public void run() {
synchronized (startupShutdownMonitor) {
doClose();
}
}
};
Runtime.getRuntime().addShutdownHook(this.shutdownHook);
}
}


@Override
public void close() {
synchronized (this.startupShutdownMonitor) {
// 实际关闭的入口
doClose();
// If we registered a JVM shutdown hook, we don't need it anymore now:
// We've already explicitly closed the context.
// 如果关闭成功,则在这一步关闭钩子,一个 context 只有一个统一的 Thread 作为钩子
if (this.shutdownHook != null) {
try {
Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
}
catch (IllegalStateException ex) {
// ignore - VM is already shutting down
}
}
}
}

// 真关闭实现,但不要直接用这个实现,不然会和 shutdownHook 的重复执行产生冲突。 理论上我们所有的关闭钩子:ContextClosedEvent、DisposalBean、@PreDestroy都是从这里发出的。子类可以覆盖这个方法,也可以覆盖 onClose(这是被推荐的)
// 这个模板方法是值得我们学习的典范,一个复杂的框架全面铺开,需要好几个扩展点和抽象,而且高层次的一致抽象原则在这行代码里运用得淋漓尽致
protected void doClose() {
// Check whether an actual close attempt is necessary...
if (this.active.get() && this.closed.compareAndSet(false, true)) {
if (logger.isDebugEnabled()) {
logger.debug("Closing " + this);
}

if (!NativeDetector.inNativeImage()) {
LiveBeansView.unregisterApplicationContext(this);
}

try {
// Publish shutdown event.
// 可以直接使用当前上下文当做 source context,注意这是在关闭前发出的事件,这让很多的 bean 在被销毁以前可以得知销毁事件开始了。如果关闭线程池要在这里关闭,这样可以停止 working。make bean ready -> start working -> stop working -> destroy bean。如果可以分离的话,让全部的 stop working 早于全部的 bean destroy,则在这里实现关闭线程池是一个好的地方(位置 1)
publishEvent(new ContextClosedEvent(this));
}
catch (Throwable ex) {
logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
}

// Stop all Lifecycle beans, to avoid delays during individual destruction.
if (this.lifecycleProcessor != null) {
try {
// 有一种 Lifecycle beans,我们目前很少用到,但确实要先关闭
// 在这里我们也可以实现关闭线程池(位置 2)
this.lifecycleProcessor.onClose();
}
catch (Throwable ex) {
logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
}
}

// Destroy all cached singletons in the context's BeanFactory.
// 包括 InitDestroyAnnotationBeanPostProcessor 调用 DisposableBeanAdapter,这个 bean 会反射调用 @PostConstruct,和 Disposal 的 destroy。这里的 bean 其实大部分是 singletonBean,而且底层会穿越 registry,证明管理 bean 的层次实际上是 application -> context -> factory -> registry
destroyBeans();

// Close the state of this context itself.
closeBeanFactory();

// Let subclasses do some final clean-up if they wish...
// 要区分给子类用的钩子和给订阅者用的钩子。比如 ServletWebServerApplicationContext 会实现该勾子函数关闭内嵌的WebServer(Tomcat)。注意这个顺序,是先关闭内部资源,再关闭外部内容
onClose();

// Reset local application listeners to pre-refresh state.
if (this.earlyApplicationListeners != null) {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}

// Switch to inactive.
// context 在这一步才算初始化完成
this.active.set(false);
}
}

一个 @PreDestroy 的栈帧:

[java.lang.Thread.getStackTrace(Thread.java:1559),
com.magicliang.transaction.sys.DomainDrivenTransactionSysApplication$ExecutorsManager.destroy(DomainDrivenTransactionSysApplication.java:117),
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method),
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62),
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43),
java.lang.reflect.Method.invoke(Method.java:498),
org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389),
org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeDestroyMethods(InitDestroyAnnotationBeanPostProcessor.java:347),
org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeDestruction(InitDestroyAnnotationBeanPostProcessor.java:177),
org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:197),
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:587),
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:559),
org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:1163),
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:520),
org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:1156),
org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1106),
org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1075),
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.doClose(ServletWebServerApplicationContext.java:174),
org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:1021),
org.springframework.boot.SpringApplicationShutdownHook.closeAndWait(SpringApplicationShutdownHook.java:145),
java.lang.Iterable.forEach(Iterable.java:75),
org.springframework.boot.SpringApplicationShutdownHook.run(SpringApplicationShutdownHook.java:114),
java.lang.Thread.run(Thread.java:748)]

  1. registerShutdownHook 在非 web 程序下不一定会被调用。我们当时遇到的情况是有人在构造器里写了 new Thread(()-> abc()).run()。abc 里有个无限循环,导致了主启动线程无限卡死在这个位置,也就意味着 ContextRefresh 不能成功。造成死锁。synchronized (this.startupShutdownMonitor) 有三个地方:refresh()、registerShutdownHook()、close()。遇到这个问题最好在进入 synchronized 以前设断点,跑到 synchronized 以后使用 idea debugger 做一个 thread dump(一般的调试模式在线程的 suspend all 断点里是不接收 jstack 的连接的,即使预先连上了,jconsole 等方案也不能解读出线程的细节,看不到锁怎么被持有,是不是守护线程),看看本线程是不是在持有一个被其他线程持有的锁。这也提醒了我们,如果需要使用关闭钩子,关闭钩子最好做好命名,这样遇到死锁问题容易排查
  2. 即使手动调用,钩子里的 Thread 也不一定会被触发。
  3. 当最后一个非守护线程退出时、使用特殊的信号给 JVM ( 理论上 CTRL + C,等于kill -s INT 71914。理论上 Spring Boot 程序应该响应这个信号。但即使 kill -s TERM 46838 也无法触发 Spring Boot 自己注册的钩子)、调用 System.exit 钩子应该被执行。这可能是非交互式 shell 的 shebang 没有写成 bash 导致的。
  4. 理论上钩子和钩子之间会并行执行(如果还有非守护线程,也会以乱序并行),所以最好全局使用一个钩子入口,然后在那个钩子里安排顺序。钩子执行不完,JVM 是不会关闭的。
  5. idea 本身的断点在点击停止(正方形按钮)以后就不可用,需要依赖于日志了。
  6. @PreDestroy or implementing the destroy() of DisposableBean gets executed only when we do ctrl+c or docker stop <>. whereas it won't execute if we do docker kill <> or stopping it directly from intelij IDE。触发 Predestroy 的根因是 close 方法被调用了,close 方法被调用既包括 JVM 钩子,也包括上下文初始化异常被捕获。

SpringApplicationShutdownHook

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
// class SpringApplicationShutdownHook implements Runnable
void registerApplicationContext(ConfigurableApplicationContext context) {
addRuntimeShutdownHookIfNecessary();
synchronized (SpringApplicationShutdownHook.class) {
assertNotInProgress();
context.addApplicationListener(this.contextCloseListener);
this.contexts.add(context);
}
}

private void addRuntimeShutdownHookIfNecessary() {
if (this.shutdownHookAdded.compareAndSet(false, true)) {
addRuntimeShutdownHook();
}
}

void addRuntimeShutdownHook() {
try {
Runtime.getRuntime().addShutdownHook(new Thread(this, "SpringApplicationShutdownHook"));
}
catch (AccessControlException ex) {
// Not allowed in some environments
}
}

// 自己作为一个线程运行的 run
@Override
public void run() {
Set<ConfigurableApplicationContext> contexts;
Set<ConfigurableApplicationContext> closedContexts;
Set<Runnable> actions;
// 单类加载器内的全局锁
synchronized (SpringApplicationShutdownHook.class) {
this.inProgress = true;
contexts = new LinkedHashSet<>(this.contexts);
closedContexts = new LinkedHashSet<>(this.closedContexts);
actions = new LinkedHashSet<>(this.handlers.getActions());
}
// 本方法被执行了两次,closedContexts 是被监听下来的。第一次调用会增加一部分 context 进入 closedContexts
contexts.forEach(this::closeAndWait);
closedContexts.forEach(this::closeAndWait);
actions.forEach(Runnable::run);
}

private class ApplicationContextClosedListener implements ApplicationListener<ContextClosedEvent> {

@Override
public void onApplicationEvent(ContextClosedEvent event) {
// The ContextClosedEvent is fired at the start of a call to {@code close()}
// and if that happens in a different thread then the context may still be
// active. Rather than just removing the context, we add it to a {@code
// closedContexts} set. This is weak set so that the context can be GC'd once
// the {@code close()} method returns.
// 为了防止这个开头事件,把它加入到 weak map 里,这样如果它还能被引用的时候,JVM 钩子还能关闭它;如果它被 gc 了,则 JVM 钩子不会再关闭它
synchronized (SpringApplicationShutdownHook.class) {
ApplicationContext applicationContext = event.getApplicationContext();
SpringApplicationShutdownHook.this.contexts.remove(applicationContext);
SpringApplicationShutdownHook.this.closedContexts
.add((ConfigurableApplicationContext) applicationContext);
}
}

}

// 这个方法不怕被重复调用
private void closeAndWait(ConfigurableApplicationContext context) {
if (!context.isActive()) {
return;
}
context.close();
try {
int waited = 0;
while (context.isActive()) {
if (waited > TIMEOUT) {
throw new TimeoutException();
}
Thread.sleep(SLEEP);
waited += SLEEP;
}
}
catch (InterruptedException ex) {
Thread.currentThread().interrupt();
logger.warn("Interrupted waiting for application context " + context + " to become inactive");
}
catch (TimeoutException ex) {
logger.warn("Timed out waiting for application context " + context + " to become inactive", ex);
}
}

LifecycleProcessor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

// 它本质上是为了管理全部的 Lifecycle bean 存在的,但自身也是 Lifecycle,这又是一个组合模式
public interface LifecycleProcessor extends Lifecycle {

/**
* Notification of context refresh, e.g. for auto-starting components.
*/
void onRefresh();

/**
* Notification of context close phase, e.g. for auto-stopping components.
*/
void onClose();

}

缺省实现是在 DefaultLifecycleProcessor,它在AbstractApplicatioContext里的注册流程是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
protected void initLifecycleProcessor() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
this.lifecycleProcessor =
beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
if (logger.isTraceEnabled()) {
logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
}
}
else {
DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
defaultProcessor.setBeanFactory(beanFactory);
this.lifecycleProcessor = defaultProcessor;
beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
if (logger.isTraceEnabled()) {
logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +
"[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
}
}
}

扩展写法:

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 abstract class SpringApplicationMultiStartup extends DefaultLifecycleProcessor {
@PostConstruct
protected void postConstruct() {
initLifecycleProcessor();
}

protected void initLifecycleProcessor() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
this.lifecycleProcessor =
beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
if (logger.isTraceEnabled()) {
logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
}
}
else {
DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
defaultProcessor.setBeanFactory(beanFactory);
this.lifecycleProcessor = defaultProcessor;
beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
if (logger.isTraceEnabled()) {
logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +
"[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
}
}
}

@Override
public void onClose() {
try {
log.info("context closed, stop SpringApplicationMultiStartup");
synchronized (lock) {
if (!isRunningNow()) {
log.info("**************, already stop, skip!");
return;
}
this.stop();
}
} finally {
super.onClose();
}
}
}


参考:

1.《Spring的扩展点》
2.《Spring Bean的生命周期(非常详细)》

基本类型

ResourceLoader + BeanDefinition + BeanDefinitionRegistry = BeanDefinitionReader。ResourceLoader 只提供资源的访问功能(path、classPath、URL),BeanDefinition 是bean的前身(name、class、BeanFactory),Registry 是存放 BeanDefinition 的地方,而 BeanDefinitionReader 负责执行这些读、加载和生成的流程。

外部调用关系是:

context.refresh -> context.invokeBeanFactoryPostProcessors -> PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()) -> PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup()) -> ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry -> ConfigurationClassPostProcessor.loadBeanDefinitionsForConfigurationClass -> ConfigurationClassBeanDefinitionReader.loadBeanDefinitions

Resource

Spring 的基本获取 Bean 的形式是获取配置文件(通常是 xml),而读取配置文件,首先要解决资源抽象问题。

Resource 首先是一种抽象,这种抽象解决配置怎么可读,配置所在的资源怎么定位的问题。

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
public interface Resource {
InputStream getInputStream() throws IOException;
}

public class ClassPathResource implements Resource {

private String path;

private ClassLoader classLoader;

public ClassPathResource(String path) {
this(path, (ClassLoader)null);
}

public ClassPathResource(String path, ClassLoader classLoader) {
this.path = path;
this.classLoader = (classLoader != null ? classLoader : Thread.currentThread().getContextClassLoader());
}

@Override
public InputStream getInputStream() throws IOException {
return classLoader.getResourceAsStream(path);
}

/**
* 来自于父类
* This implementation returns a File reference for the underlying class path
* resource, provided that it refers to a file in the file system.
* @see org.springframework.util.ResourceUtils#getFile(java.net.URL, String)
*/
@Override
public File getFile() throws IOException {
URL url = getURL();
if (url.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
return VfsResourceDelegate.getResource(url).getFile();
}
return ResourceUtils.getFile(url, getDescription());
}

}

除了 Resource 以外,还有另一种获取资源的方式,那就是通过 ResourceLoader:

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

final String CLASSPATH_URL_PREFIX = "classpath:";

public Resource getResource(String location){
if (location.startsWith(CLASSPATH_URL_PREFIX)) {
return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()));
}
else {
return new ClassPathResource(location);
}
}
}

BeanDefinition

RootBeanDefinition的构造

从配置文件里映射出来的数据结构,首先绑定到 BeanDefinition 上:

1
2
3
4
5
6
7
8
9
10
11
12
public class BeanDefinition {
// bean名称
private String beanName;
// bean的class对象
private Class beanClass;
// bean的class的包路径
private String beanClassName;
// bean依赖属性,就这,似乎就足以表达复杂的 XML 了
private PropertyValues propertyValues = new PropertyValues();

// 某些定义会带入 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
    private List<PropertyValue> propertyValues = new ArrayList<PropertyValue>();

public void addPropertyValue(PropertyValue propertyValue) {
propertyValues.add(propertyValue);
}

public List<PropertyValue> getPropertyValues() {
return this.propertyValues;
}

/**
* 这个 kv 值是可以被直接使用的
*/
public class PropertyValue {
private final String name;
private final Object value;

public PropertyValue(String name, Object value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public Object getValue() {
return value;
}
}

XmlBeanDefinitionReader

事实上现在的 BeanDefinitionReader 接口只有几个子类:

  • AbstractBeanDefinitionReader
  • GroovyBeanDefinitionReader
  • PropertiesBeanDefinitionReader
  • XmlBeanDefinitionReader

还有非 BeanDefinitionReader 的子类的其他定义读取器:AnnotatedBeanDefinitionReader/AnnotatedBeanDefinitionReader/ClassPathBeanDefinitionScanner。

ClassPathBeanDefinitionScanner 会读取各种注解和配置,进行 registerBean 操作。

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
public class XmlBeanDefinitionReader implements BeanDefinitionReader {
// BeanDefinition注册到BeanFactory接口
private BeanDefinitionRegistry registry;
// 资源载入类
private ResourceLoader resourceLoader;

public XmlBeanDefinitionReader(BeanDefinitionRegistry registry, ResourceLoader resourceLoader) {
this.registry = registry;
this.resourceLoader = resourceLoader;
}

@Override
public void loadBeanDefinitions(String location) throws Exception{
InputStream is = getResourceLoader().getResource(location).getInputStream();
doLoadBeanDefinitions(is);
}

public BeanDefinitionRegistry getRegistry(){
return registry;
}

public ResourceLoader getResourceLoader(){
return resourceLoader;
}

protected void doLoadBeanDefinitions(InputStream is) throws Exception {
// 1. 获取 document的 factory
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
// 2. 把资源转化为 w3c 规定的 document
Document document = builder.parse(is);
// 3. 注册 bean 定义
registerBeanDefinitions(document);
is.close();
}

protected int registerBeanDefinitions(Document document) {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}


protected void processBeanDefinition(Element ele) {
String name = ele.getAttribute("id");
String className = ele.getAttribute("class");
if(className==null || className.length()==0){
throw new IllegalArgumentException("Configuration exception: <bean> element must has class attribute.");
}
if(name==null||name.length()==0){
name = className;
}
// 实际上也是用 new 方法来生成 beanDefinition,把 attribute 转换成为 BeanDefinition 的属性
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setBeanClassName(className);
processBeanProperty(ele,beanDefinition);
getRegistry().registerBeanDefinition(name, beanDefinition);
}

protected void processBeanProperty(Element ele, BeanDefinition beanDefinition) {
NodeList childs = ele.getElementsByTagName("property");
for (int i = 0; i < childs.getLength(); i++) {
Node node = childs.item(i);
if(node instanceof Element){
Element property = (Element)node;
// 把内部的 attribute 转换为 PropertyValues
String name = property.getAttribute("name");
String value = property.getAttribute("value");
if(value!=null && value.length()>0) {
beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(name, value));
} else {
String ref = property.getAttribute("ref");
if(ref==null || ref.length()==0){
throw new IllegalArgumentException("Configuration problem: <property> element for "+
name+" must specify a value or ref.");
}
BeanReference reference = new BeanReference(ref);
beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(name, reference));
}
}
}
}
}

BeanDefinitionRegistry

BeanDefinitionRegistry 则是另一个维护一大套 map 的接口:

1
2
3
public interface BeanDefinitionRegistry {
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
}

通常 BeanDefinitionRegistry 和 BeanFactory 被实现在同一个实现里:

1
2
3
4
5
6
7
8
9
10
public class DefaultListableBeanFactory extends AbstractBeanFactory implements ConfigurableListableBeanFactory,BeanDefinitionRegistry {

private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();
private List<String> beanDefinitionNames = new ArrayList<String>();

public void registerBeanDefinition(String beanName,BeanDefinition beanDefinition) {
beanDefinitionMap.put(beanName, beanDefinition);
beanDefinitionNames.add(beanName);
}
}

BeanFactory

BeanFactory 自有其继承体系:

  • SingletonBeanRegistry: 定义了对单例缓存池相关的操作,如将bean注册到单例缓存池中
  • ConfigurableBeanFactory: 可配置的BeanFactory,定义了各种各样的配置能力,如bean的作用域,bean的classLoader,添加bean的后置处理器,设置bean的创建状态,销毁bean等等
  • AutowireCapableBeanFactory: 能进行自动装配的BeanFactory,这可能是我们最为熟悉的BeanFactory,定义了自动装配的类型(byName/byType),createBean, autowireBean, 自动装配属性, populateBean, initializeBean, 对于与bean生命周期相关的方法都将在这里体现
  • ListableBeanFactory: 对BeanFactory的增强,定义了一系列根据beanType获取bean或者beanName的方法
  • ConfigurableListableBeanFactory: 对ConfigurableBeanFactory的增强,定义了忽略bean的类型、缓存bean定义、预实例化单例bean等方法
  • BeanDefinitionRegistry: bean定义注册器,定义了与bean定义相关的方法
  • DefaultSingletonBeanRegistry: 单例bean注册器,定义了三级缓存,其实就是三个Map属性
  • FactoryBeanRegistrySupport: 提供对FactoryBean的支持
  • AbstractBeanFactory: 实现了一系列操作IOC容器的功能,但最终的createBean依旧交由子类AbstractAutowireCapableBeanFactory完成
  • AbstractAutowireCapableBeanFactory: 实现了创建bean的功能,所有与创建bean的相关的功能都在这里
  • DefaultListableBeanFactory: 在以上父类的功能基础上实现了ConfigurableBeanFactory和BeanDefinitionRegistry接口,定义了一些存放Bean定义相关信息的Map
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
public interface BeanFactory {

Object getBean(String beanName);
}

// 这个抽象类是整个模板方法里最重要的
public abstract class AbstractBeanFactory implements ConfigurableListableBeanFactory {
private Map<String, Object> singleObjects = new ConcurrentHashMap<String, Object>();

protected abstract BeanDefinition getBeanDefinitionByName(String beanName);

// 所有的创建 bean 的方法的入口
protected Object createInstance(BeanDefinition beanDefinition) {
try {
if(beanDefinition.getBeanClass() != null){
return beanDefinition.getBeanClass().newInstance();
} else if(beanDefinition.getBeanClassName() != null){
try {
Class clazz = Class.forName(beanDefinition.getBeanClassName());
beanDefinition.setBeanClass(clazz);
return clazz.newInstance();
} catch (ClassNotFoundException e) {
throw new RuntimeException("bean Class " + beanDefinition.getBeanClassName() + " not found");
}
}
} catch (Exception e) {
throw new RuntimeException("create bean " + beanDefinition.getBeanName() + " failed");
}
throw new RuntimeException("bean name for " + beanDefinition.getBeanName() + " not define bean class");
}

/**
* 从 bean definition 里生成 bean,这个方法在 getBean 里才执行,它可以被优化成一个惰性求值的方法
* 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
*/
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

final String beanName = transformedBeanName(name);
Object bean;

// 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 + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
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);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}

if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}

try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);

// 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)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}

// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
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);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}

// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
}
// 选定一个特定的类,在注解注入的地方做好断点(字段上可以做访问和修改断点),就能知道在整个 Spring 体系里在哪里触发了某段初始化流程
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {

// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 我们常说的实例化,instantiation 在这里
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}

// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}

// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

// Initialize the bean instance.
Object exposedObject = bean;
try {
// autowire 在这里实现
populateBean(beanName, mbd, instanceWrapper);
// 在这里实现 initialization,所以 autowire 比各种 init 钩子要早
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}

if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
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);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}

return exposedObject;
}


/**
* Initialize the given bean instance, applying factory callbacks
* as well as init methods and bean post processors.
* <p>Called from {@link #createBean} for traditionally defined beans,
* and from {@link #initializeBean} for existing bean instances.
* @param beanName the bean name in the factory (for debugging purposes)
* @param bean the new bean instance we may need to initialize
* @param mbd the bean definition that the bean was created with
* (can also be {@code null}, if given an existing bean instance)
* @return the initialized bean instance (potentially wrapped)
* @see BeanNameAware
* @see BeanClassLoaderAware
* @see BeanFactoryAware
* @see #applyBeanPostProcessorsBeforeInitialization
* @see #invokeInitMethods
* @see #applyBeanPostProcessorsAfterInitialization
*/
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
// 在这里调用各种 aware 方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 在这里使用 BeforeInitialization 的 BeanPostProcessor
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 在这里使用 AfterInitialization 的 BeanPostProcessor,通常 aop 的 bean 在这里被 wrap
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

return wrappedBean;
}

在 AbstractAutowireCapableBeanFactory 里有 createBean 的一个例子:

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
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {

if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;

// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}

// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}

try {
// 注意,这里可以给 InstantiationAwareBeanPostProcessor 之类的后处理器一个机会,进行实例化的一个拦截,可以在这里注册一系列的自己的处理器
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}

try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}

DefaultSingletonBeanRegistry

三级缓存与循环依赖

三级缓存的一个典型应用,是用来解决“单例的循环依赖”。

循环依赖自查表

我们可以看到,先初始化的 bean 如果构造器里依赖了另一个循环依赖 bean,则循环依赖问题无法被三级缓存解决。

三级缓存概况

AB循环依赖

创建A实例,实例化的时候把A对象⼯⼚放⼊三级缓存,表示A开始实例化了,虽然我这个对象还不完整,但是先曝光出来让大家知道(exposedBean)。

主对象被放入三级缓存

A注⼊属性时,发现依赖B,此时B还没有被创建出来,所以去实例化B

同样,B注⼊属性时发现依赖A,它就会从缓存里找A对象。依次从⼀级到三级缓存查询A,从三级缓存通过对象⼯⼚拿到A,发现A虽然不太完善,但是存在,把A放⼊⼆级缓存,同时删除三级缓存中的A,此时,B已经实例化并且初始化完成,把B放入⼀级缓存。

主初始化对象可以被放入二级缓存,而非构造器注入的对象,可以使用不完整的成员构造自己,进而放入一级缓存里

接着A继续属性赋值,顺利从⼀级缓存拿到实例化且初始化完成的B对象,A对象创建也完成,删除⼆级缓存中的A,同时把A放⼊⼀级缓存。

最后,⼀级缓存中保存着实例化、初始化都完成的A、B对象。

一级缓存全装满

三级缓存的工作模式的另一种解释

[5][为什么一定要有三级缓存?]

ApplicationContext

BeanFactory 是 Spring 早期设计的抽象,应该尽量不被直接使用,当代的 Spring 应该使用更加现代的抽象 ApplicationContext,如:

1
2
public interface ApplicationContext extends BeanFactory {
}

我们常见的子类有:

  • ClasspathXmlApplicationContext
  • AnnotationConfigApplicationContext
  • GenericWebApplicationContext
  • AnnotationConfigServletWebApplicationContext(现代 SpringBoot 的 web 上下文就是这个)
1
2
3
4
5
6
7
8
9
10
11
12
13
public class ClasspathXmlApplicationContext extends AbstractApplicationContext {
private String location;

// 这个构造器有一个很特别的地方,那就是在构造器里直接 refresh
public ClasspathXmlApplicationContext(String location) {
this.location = location;
try {
refresh();
} catch (Exception e) {
e.printStackTrace();
}
}
}

这里引用的最重要的 refresh 方法,就是所有谈到 Spring 的文档里都必然谈到的 AbstractApplicationContext 里的 refresh()(经典的模板方法模式,所有的扩展点的顺序要依照它设定的方法来实现)。

如果说 BeanFactory 主要是 IOC 的容器的话,提供的主要是生命周期管理的功能。Context 则给 BeanFactory 外部加上了 BeanDefinitionRegistry 的管理、消息机制和事件机制的处理。对于 Spring 而言,初始化也是一种刷新,上下文的内容的加载,就是一种刷新:

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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
    @Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing
// 主要是设置开始时间以及标识active标志位为true
prepareRefresh();

// Tell the subclass to refresh the internal bean factory.
// 先获取一个 bean 工厂,注意,在它的子类(比如 GenericApplicationContext)的实现里,总是先刷新一下 BeanFactory,然后加载配置文件,把自己的成员的 beanFactory 返回到这一层。ConfigurableListableBeanFactory 这个类型就是 Spring源码里的最抽象类型了,不是简单的 BeanFactory 接口,而且只和 DefaultListableBeanFactory 差了两层。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// 先装配这个 beanFactory,这是在填充基础属性。
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);

try {
// 没有生成任何的 bean,就先后处理这个 beanFactory,所以这里就会直接触发 bean 工厂的后处理,如 web 项目中配置 ServletContext,还有更多的 addBeanPostProcessor 和 ignoreDependencyInterface,这里是不用任何后处理器的后处理
// 这一部是留给子类扩展用的。
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// 一般到这一步为止,只有 SpringApplication 作为一个外部 bean 初始化了,其他都是各种 internalProcessor

// 实例化 + 调用注册好的 BeanFactoryPostProcessors,这是一大段后处理:
// 1. parse 所有的 configuration Class。这会带来各种 BeanFactoryPostProcessor。
// 2. 执行各种 BeanDefinitionReader,实际上是对各种 bean definition 的 PropertyValue 进行后处理(具体一点,在这里进行加载)。注意,这里是利用之前注册的扩展点来实现后处理,后处理里才真正使用生成了各种各样的 beanDefinition。所以我们实际上是在 BeanFactory 的后处理里,先进行 BeanDefinitionReistry 的后处理。
// 3. 并且初始化了大部分的类似 EntityManager 之类的内部资源管控 Bean - meta service bean。
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);

// 只是实例化,并注册 bean 后处理器,但不执行。
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);

// 初始化消息源
// Initialize message source for this context.
initMessageSource();

// 初始化应用事件多播器(和listener 不同)
// Initialize event multicaster for this context.
initApplicationEventMulticaster();

// 调用子类的刷新生命周期的中间扩展点,如初始化特殊的bean,一般在这里创建 tomcat
// Initialize other special beans in specific context subclasses.
onRefresh();

// 注册监听器,所有的 bean 初始化完了,才会初始化监听器
// Check for listener beans and register them.
registerListeners();

// 对 BeanFactory 初始化进行收尾,这一步内部做了大量的 getBean 工作,可以说主要的非 config 和非 PostProcessor 管理的bean,所有的 autowired 的 bean 都是在这一步被创建出来的。bean后处理器,是bean创建前后才调用的,也是 BeanFactoryInitialization 的一部分。
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

// 对刷新进行收尾,初始化生命周期,发布容器事件(如 ContextRefreshedEvent 是在这一步被发出的)
// Last step: publish corresponding event.
finishRefresh();
}

catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}

// 销毁已经创建的单例bean
// Destroy already created singletons to avoid dangling resources.
destroyBeans();

// 重置active标识
// Reset 'active' flag.
cancelRefresh(ex);

// Propagate exception to caller.
throw ex;
}

finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}


/**
* Prepare this context for refreshing, setting its startup date and
* active flag as well as performing any initialization of property sources.
*/
protected void prepareRefresh() {
// Switch to active.
// 先把容器状态设置起来
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);

if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
// 在这一步初始化所有的属性源,自定义的属性源和 configurer 在这一步会生效
// Initialize any placeholder property sources in the context environment.
initPropertySources();

// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();

// 初始化应用监听器缓存
// Store pre-refresh ApplicationListeners...
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}

// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}


/**
* beanfactory 的基础后处理器的加载就在这里实现,注意,这里只是“准备”,各种后处理器和 bean 的加载还没有生效,最多只是 registerSingleton。这个方法是 Spring 内部动态注册自身内部 bean 的常用方法,
* Configure the factory's standard context characteristics,
* such as the context's ClassLoader and post-processors.
* @param beanFactory the BeanFactory to configure
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
if (!shouldIgnoreSpel) {
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
}
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

// Configure the bean factory with context callbacks.
// 有些 BeanPostProcessor 是需要一个 context 作为上下文的
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 这些接口以后都由 beanFactory 自行注入(BeanFactoryAware or ApplicationContext through ApplicationContextAware.),而不由 autowiring 来注入
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);

// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);

// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 感知是否是 graalvm 的镜像正在构建,以及当前的 beanFactory 是否已经包含 loadTimeWeaver 这个 bean
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// 临时注册各种各样的单例 bean 作为全局配置的一部分
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
// 因为 beanFactory 本身也实现了BeanDefinitionRegistry,所以在 beanFactory 也会更新
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
}

public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// getBean 可能无意中触发 processors 的实例化,这里面有非常细的初始化流程,严格保证 order 语义不被破坏。这里大量使用 beanFactory.isTypeMatch 来保障所有的类型注解能够帮我们过滤出不同的列表
// WARNING: Although it may appear that the body of this method can be easily
// refactored to avoid the use of multiple loops and multiple lists, the use
// of multiple lists and multiple passes over the names of processors is
// intentional. We must ensure that we honor the contracts for PriorityOrdered
// and Ordered processors. Specifically, we must NOT cause processors to be
// instantiated (via getBean() invocations) or registered in the ApplicationContext
// in the wrong order.
//
// Before submitting a pull request (PR) to change this method, please review the
// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
// to ensure that your proposal does not result in a breaking change:
// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22

// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();

if (beanFactory instanceof BeanDefinitionRegistry) {
// 在这里我们可以看到我们内部包装的 beanFactory 也是个 BeanDefinition 注册表
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 这里的 beanFactoryPostProcessors 是 context 的成员变量,证明注册也就是直接放在一个成员里而已
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}

// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

// 在这一步可以通过类型可以获取 beanNames
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 对 Ordered 的注解缺省的比较器是 OrderComparator
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 在对 beanFactory 进行后处理之前,先对 registry 进行后处理,所以 BeanDefinitionRegistry、BeanFactory、Bean 的后处理是有严格顺序的。这个隐藏的 invoke 显示,没有单独的 BeanDefinitionRegistry post process
// 这里的各种 getApplicationStartup 是一种类似 Cat 的 business metric
// 我们在控制台里经常能看到的 doLoadBeanDefinitions 日志,都在这里面被打出来,各种 configuration bean 也是在这里面被生产出来的,第一个 currentRegistryProcessor 至少是 ConfigurationClassPostProcessor。在很多文献里,这里被称作“解析配置类”。我们对 configuration class 的解析,是通过执行这些类的 pp(后处理器)来实现的。
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();

// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();

// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
}

// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}

else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}

// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}

// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
// 同样,invokeBeanFactoryPostProcessors 这个方法会被多次调用,有大量的基础 bean,比如各种 EntityManager 是在这里被 create 出来的
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
processConfigBeanDefinitions(registry);
}
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
// 放置候选配置类
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
String[] candidateNames = registry.getBeanDefinitionNames();
// 遍历之前注册的所有bean定义,找到其中的配置类,其实就是我们自己传进来的配置类
for (String beanName : candidateNames) {
// ...省略校验过程...
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
// 这里要注意,有 full 和 lite 两种类型
// 检查是否是有 @Configuration 注解的 BeanDifinition -> full 类型的配置类 -> 会把配置类替换成动态代理类
// 或者该类包含 @Component @ComponentScan @Import @ImportResource @Bean 注解的其中之一 -> lite类型的配置类 -> 不会替换成动态代理类。被 @Component 注解的类不能是接口。
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// ....省略片段....
// 实例化一个配置类解析器
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);

do {
// 解析配置类
parser.parse(candidates);
parser.validate();
// parser.getConfigurationClasses()就是拿到刚刚解析完放到map中的配置类
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);

// 这里处理@Import导入的beanDefintion和配置类中的@Bean
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
// 以下逻辑是找出未解析的配置类,如@Bean和ImportBeanDefinitionRegistrar所引入的
candidates.clear();
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);
// 将是配置类并且没有解析过的BeanDefinition放到候选集合中继续解析
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
}

// 一段自定义补完 BeanDefinitionRegistry 里缺少的本 bean 的定义的方法,这有点 visitor pattern 的味道
private void register(BeanDefinitionRegistry registry) {
if (!registry.containsBeanDefinition(BEAN_NAME)) {
// 注意 rootBeanDefinition 和抽象 BeanDefinition 的关联关系
BeanDefinition definition = BeanDefinitionBuilder
.rootBeanDefinition(SharedMetadataReaderFactoryBean.class, SharedMetadataReaderFactoryBean::new)
.getBeanDefinition();
registry.registerBeanDefinition(BEAN_NAME, definition);
}
}

// 真正加载所有的 configuration 的地方,这内部会交叉运用各种 Reader 如:XmlBeanDefinitionReader
this.reader.loadBeanDefinitions(configClasses);

// 动态生成 tomcat 的方法
@Override
public WebServer getWebServer(ServletContextInitializer... initializers) {
if (this.disableMBeanRegistry) {
Registry.disableRegistry();
}
Tomcat tomcat = new Tomcat();
File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
tomcat.setBaseDir(baseDir.getAbsolutePath());
for (LifecycleListener listener : this.serverLifecycleListeners) {
tomcat.getServer().addLifecycleListener(listener);
}
Connector connector = new Connector(this.protocol);
connector.setThrowOnFailure(true);
tomcat.getService().addConnector(connector);
customizeConnector(connector);
tomcat.setConnector(connector);
tomcat.getHost().setAutoDeploy(false);
configureEngine(tomcat.getEngine());
for (Connector additionalConnector : this.additionalTomcatConnectors) {
tomcat.getService().addConnector(additionalConnector);
}
prepareContext(tomcat.getHost(), initializers);
return getTomcatWebServer(tomcat);
}


/**
* 在这里把所有的非 lazy 的单例给初始化了,我们的各种 Service、Component 在这里被初始化
* Finish the initialization of this context's bean factory,
* initializing all remaining singleton beans.
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}

// Register a default embedded value resolver if no BeanFactoryPostProcessor
// (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}

// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}

// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);

// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();

// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}

对 bean 的管理的全流程

bean的生命周期
bean的生命周期.xmind
创建bean
bean的构造流程
销毁bean生命周期的扩展点
BeanFactory生产Bean的过程是怎样的

BeanProstProcessor 体系

ApplicationContexts 可以在其 BeanDefinition 中自动检测 BeanPostProcessor Bean,并将其应用于随后创建的所有 Bean 实例。

BeanProstProcessor继承树
BeanProcessor主要流程
MergedBeanDefinitionPostProcessor
SmartInstantiationAwareBeanPostProcessor
DestructionAwareBeanPostProcessor

如何实现自动装配?

对于 AutoWired 而言,答案是使用 AutowiredAnnotationBeanPostProcessor 的生命周期钩子。可见,我们所有的 field injection 相关的注入,都要考虑 BeanPostProcessor 的钩子方法进行扩展。

对于 field injection,最关键的方法是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 它是被 populateBean 这个方法调用的
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// 这里的 pvs 就是我们要注入的真正的值。这里的 InjectionMetadata 很容易实现为自己的一个子类,至少要实现里头类似 getResource之类的钩子
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}

和之前我设计和实现的缓存注入的思路是一样的,实际上所有的动态注入的 annotation 都应该这样设计,才能满足 Spring 的依赖管理的布局。

这个流程需要看:

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
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName);

if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}

Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}

// @Bean 类型的工厂方法的调用入口在这里
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}

// Shortcut when re-creating the same bean...
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
}

// Candidate constructors for autowiring?
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}

// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}

// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
}

Spring Boot 的初始化流程

Application 视角

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
    // 注意,Application 本身是一个比 Context 更大的概念
// 生成一个 SpringApplication,通过 run 获得一个 ConfigurableApplicationContext
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}

@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// spring boot 获取主类的方法很妙
this.mainApplicationClass = deduceMainApplicationClass();
}

private Class<?> deduceMainApplicationClass() {
try {
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
if ("main".equals(stackTraceElement.getMethodName())) {
return Class.forName(stackTraceElement.getClassName());
}
}
}
catch (ClassNotFoundException ex) {
// Swallow and continue
}
return null;
}


/**
* Run the Spring application, creating and refreshing a new
* {@link ApplicationContext}.
* @param args the application arguments (usually passed from a Java main method)
* @return a running {@link ApplicationContext}
*/
public ConfigurableApplicationContext run(String... args) {
long startTime = System.nanoTime();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
// 确定 awt 的相关无窗体配置
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// activeProfiles、defaultProfile、propertySource
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
// 设置一些基础的环境,给 context 增加一些单例 bean 的注册信息,增加一些 beanFactory 的后处理器和 bean 的后处理器
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// 这里可以说是 Spring 的真正初始化全流程了,是在 context自身的 refresh 方法调用以前,先装一个钩子:shutdownHook.registerApplicationContext(context); 关闭钩子一开始就是个本 Application 的成员变量
refreshContext(context);
afterRefresh(context, applicationArguments);
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
listeners.started(context, timeTakenToStartup);
// 我们自己定义的 runner 其实可以被分为两类,ApplicationRunner 和 CommandLineRunner,这里统一使用 applicationArguments 来运行了,底层有 getBean 的方法
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}

ServletWebServerApplicationContext 里有调用父类的刷新方法和创建 WebServer 的流程:

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
@Override
public final void refresh() throws BeansException, IllegalStateException {
try {
super.refresh();
}
catch (RuntimeException ex) {
WebServer webServer = this.webServer;
if (webServer != null) {
webServer.stop();
}
throw ex;
}
}


// 这个方法是被父类 refresh 调用进来的
@Override
protected void onRefresh() {
super.onRefresh();
try {
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}

Context Refresh 的全流程

自顶向下拆解Context刷新的流程

出处。讲 import 和 componentScan 讲得很好,这一流程实际上是 ConfigurationClassPostProcessorconfiguration.processConfigBeanDefinitions 的一部分。也要关注 ConfigurationClassParser/ConfigurationClassBeanDefinitionReader/ComponentScanAnnotationParser/ClassPathBeanDefinitionsScanner。这里面还讲了 @MapperScan 和 MapperScannerRegistrar 怎样利用 BeanDefinition机制,让 constructor 和 FactoryBean 把 interface class 生成 Spring Bean。

1
2
3
4
5
definition = (GenericBeanDefinition) holder.getBeanDefinition();
// 将原来的接口mapper放到beanDefintion的构造方法参数中,以指定的构造方法实例化。
definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName());
// 注意这里:将原来的beanClass替换成FactoryBean了! bean definition 的扩展点在这。
definition.setBeanClass(this.mapperFactoryBean.getClass());