# springboot启动原理分析
# 创建SpringApplication
进入
SpringApplication
时,会初始化参数执行构造方法
SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources)
this.webApplicationType = WebApplicationType.deduceFromClasspath()就是判断当前web应用的类型,是响应式的还是servlet
this.bootstrapRegistryInitializers = getBootstrapRegistryInitializersFromSpringFactories()
在该项目的所有依赖中的
spring.factories
文件中,寻找Bootstrapper,也就像这个一样根据EnableAutoConfiguration进行查找
getSpringFactoriesInstances(type, new Class<?>[] {})
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class))同样也是在factories中,查找ApplicationContextInitializer.class
this.mainApplicationClass = deduceMainApplicationClass()寻找主类方法,也就是含有main方法的类
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; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14"main".equals(stackTraceElement.getMethodName()如果循环到的类,方法名是main,那么就是主类,并且会使用这个主类创建一个对象
上面的创建SpringApplication的过程,其实就是return new SpringApplication(primarySources).run(args)中的new SpringApplication(primarySources)过程,当创建springApplication完成后,就会调用后面的run()方法运行springapplication
# 运行SpringApplication
记录应用启动的开始时间
stopWatch.start()
创建Bootstrap,这个Bootstrap就是我们从spring.factories中配置的
DefaultBootstrapContext bootstrapContext = createBootstrapContext()
private DefaultBootstrapContext createBootstrapContext() { DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext(); this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext)); return bootstrapContext; }
1
2
3
4
5获取到所有之前的 bootstrappers 挨个执行 intitialize() 来完成对引导启动器上下文环境设置
让当前应用进入headless模式
configureHeadlessProperty()----> java.awt.headless...
获取当前程序的运行监听器
SpringApplicationRunListeners listeners = getRunListeners(args),是从
spring.factories
中调用getSpringFactoriesInstances()拿取的 SpringApplicationRunListener
在此文件中,也是存在一个
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
2
3
遍历 SpringApplicationRunListener 调用 starting 方法;
相当于通知所有感兴趣系统正在启动过程的人,项目正在 starting
listeners.starting(bootstrapContext, this.mainApplicationClass)
保存命令行参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args)
准备环境 prepareEnvironment();
返回或者创建基础环境信息对象。StandardServletEnvironment
配置环境信息对象。
- 读取所有的配置源的配置属性值。
绑定环境信息 监听器调用 listener.environmentPrepared();通知所有的监听器当前环境准备完成
创建ioc容器,这是最重要的一步,根据当前的web应用类型,是servlet还是其他的,创建对应容器
context = createApplicationContext()
ApplicationContextFactory DEFAULT = (webApplicationType) -> { try { switch (webApplicationType) { case SERVLET: return new AnnotationConfigServletWebServerApplicationContext(); case REACTIVE: return new AnnotationConfigReactiveWebServerApplicationContext(); default: return new AnnotationConfigApplicationContext(); } } catch (Exception ex) { throw new IllegalStateException("Unable create a default ApplicationContext instance, " + "you may need a custom ApplicationContextFactory", ex); } };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16准备当前容器的基本信息
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner)
设置环境
ioc容器的后置处理流程
postProcessApplicationContext(context)
应用初始化器--->applyInitializers(context)
protected void applyInitializers(ConfigurableApplicationContext context) { for (ApplicationContextInitializer initializer : getInitializers()) { Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(), ApplicationContextInitializer.class); Assert.isInstanceOf(requiredType, context, "Unable to call initializer."); initializer.initialize(context); } }
1
2
3
4
5
6
7
8遍历所有的 ApplicationContextInitializer 。调用 initialize.。来对ioc容器进行初始化扩展功能
遍历所有的 listener 调用 contextPrepared。EventPublishRunListenr;通知所有的监听器****contextPrepared
所有的监听器 调用 contextLoaded。通知所有的监听器 contextLoaded;
listeners.contextPrepared(context)
得到所有的bean,并且注册
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
1
2
**刷新IOC容器。**refreshContext()
创建容器中的所有组件(Spring注解
容器刷新完成后工作?afterRefresh
所有监听 器 调用 listeners.started(context); 通知所有的监听器 started
*调用所有runners;**callRunners()
获取容器中的 ApplicationRunner
获取容器中的 CommandLineRunner
合并所有runner并且按照@Order进行排序
遍历所有的runner。调用 run 方法
- 如果以上有异常,**
- 调用Listener 的 failed
- 调用所有监听器的 running 方法 listeners.running(context); 通知所有的监听器 running
- **running如果有问题。继续通知 failed 。**调用所有 Listener 的 **failed;**通知所有的监听器 failed
# 自定义事件监听事件组
我们自定义事件监听,只需要考虑程序启动的时候,是去哪里找到这个监听器就行,在程序启动的时候,监听器会从spring.factories
和context容器中进行拿取
其中,从spring.factories
中拿取的有
org.springframework.context.ApplicationContextInitializer
org.springframework.context.ApplicationListener
org.springframework.boot.SpringApplicationRunListener
这三个
从容器中拿取的有
CommandLineRunner
ApplicationRunner
因为有三个需要从spring.factories
中拿取,所以我们就要在META-INF
下创建一个spring.factories
文件
package cn.vipblogs.test.listener;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("MyApplicationContextInitializer ....initialize.... ");
}
}
package cn.vipblogs.test.listener;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
public class MyApplicationListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("MyApplicationListener.....onApplicationEvent...");
}
}
package cn.vipblogs.test.listener;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Order(1)
@Component
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("MyApplicationRunner...run...");
}
}
package cn.vipblogs.test.listener;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* 应用启动做一个一次性事情
*/
@Order(2)
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("MyCommandLineRunner....run....");
}
}
package cn.vipblogs.test.listener;
import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
public class MySpringApplicationRunListener implements SpringApplicationRunListener {
private SpringApplication application;
public MySpringApplicationRunListener(SpringApplication application, String[] args){
this.application = application;
}
@Override
public void starting(ConfigurableBootstrapContext bootstrapContext) {
System.out.println("MySpringApplicationRunListener....starting....");
}
@Override
public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
System.out.println("MySpringApplicationRunListener....environmentPrepared....");
}
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
System.out.println("MySpringApplicationRunListener....contextPrepared....");
}
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
System.out.println("MySpringApplicationRunListener....contextLoaded....");
}
@Override
public void started(ConfigurableApplicationContext context) {
System.out.println("MySpringApplicationRunListener....started....");
}
@Override
public void running(ConfigurableApplicationContext context) {
System.out.println("MySpringApplicationRunListener....running....");
}
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
System.out.println("MySpringApplicationRunListener....failed....");
}
}
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
org.springframework.context.ApplicationContextInitializer=\
cn.vipblogs.test.listener.MyApplicationContextInitializer
org.springframework.context.ApplicationListener=\
cn.vipblogs.test.listener.MyApplicationListener
org.springframework.boot.SpringApplicationRunListener=\
cn.vipblogs.test.listener.MySpringApplicationRunListener
2
3
4
5
6
7
8
从启动打印就可以看出,他们执行的时机