Spring Boot启动流程源码分析

版本:2.1.1.RELEASE

使用main方法启动Spring Boot应用:

1
2
3
public static void main(String[] args) {
SpringApplication.run(DingtalkApplication.class, args);
}

进入SpringApplication类的run方法最终实现位置:

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
public ConfigurableApplicationContext run(String... args) {
// 1. 启动计时
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
// 2. 回调接口SpringBootExceptionReporter用于支持自定义spring应用程序启动错误的报告
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
// 3. 配置启用Java headless模式
configureHeadlessProperty();
// 4. 获取Spring应用run方法的监听器集合并启动所有的监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
// 5. 提供对用于运行SpringApplication的参数的访问
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
// 6. 创建和配置环境
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
// 7. 配置忽略BeanInfo类的加载
configureIgnoreBeanInfo(environment);
// 8. 打印Banner
Banner printedBanner = printBanner(environment);
// 9. 创建ApplicationContext
context = createApplicationContext();
// 10. 获取异常报告实例列表
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 11. 准备应用上下文
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
// 12. 刷新底层的ApplicationContext
refreshContext(context);
// 13. protected方法,应用上下文刷新后,子类可实现此方法用于后续的操作
afterRefresh(context, applicationArguments);
// 14. 打印应用启动信息
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
// 15. 启动实现了CommandLineRunner 和 ApplicationRunner 接口的类的run方法
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}

try {
// 16. 在run 方法结束之前立即调用,发布事件,应用程序已准备好接受服务请求
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}

run方法源码上注释了大概流程,接下来继续深入重点流程的源码。

流程4,获取Spring应用run方法的监听器集合并启动所有的监听器:

getRunListeners(String[] args) 方法源码:

1
2
3
4
5
   private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
SpringApplicationRunListener.class, types, this, args));
}

返回SpringApplicationRunListeners 实例,直接看构造方法的第二个参数的getSpringFactoriesInstances方法实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
   private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
Class<?>[] parameterTypes, Object... args) {
// 1. 获取类加载器
ClassLoader classLoader = getClassLoader();
// 2. 获取指定类型的工厂实现类的完全限定类名集合
Set<String> names = new LinkedHashSet<>(
SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 3. 根据传入的完全限定类名集合创建对应工厂实例
List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
classLoader, args, names);
// 4. 根据工厂实例上的@Order注解指定的顺序排序
AnnotationAwareOrderComparator.sort(instances);
return instances;
}

该方法第一个参数这里传入的是SpringApplicationRunListener 接口,会获取该接口所在类加载器下的“META-INF/spring.factories”属性文件
设置的接口实现org.springframework.boot.context.event.EventPublishingRunListener,然后调用该类的构造方法实例化:

1
2
3
4
5
6
7
8
   public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
this.initialMulticaster = new SimpleApplicationEventMulticaster();
for (ApplicationListener<?> listener : application.getListeners()) {
this.initialMulticaster.addApplicationListener(listener);
}
}

该类的主要作用是作为应用启动过程的事件发布监听器,可以看到构造方法中实例化了一个简单的应用事件多播器SimpleApplicationEventMulticaster 并遍历添加应用启动事件监听器。

流程4最后调用listeners.starting() 启动监听器,实现源码:

1
2
3
4
5
   @Override
public void starting() {
this.initialMulticaster.multicastEvent(
new ApplicationStartingEvent(this.application, this.args));
}

该方法多播一个ApplicationStartingEvent实例(应用启动事件),事件源是SpringApplication本身。
接下来就是解析事件类型并调用对应的事件监听器了,感兴趣的可以自己深入。深入之前需要对Spring事件机制有所了解,
推荐此文Spring事件机制

流程6. 创建和配置环境:

prepareEnvironment(listeners, applicationArguments)方法实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
   private ConfigurableEnvironment prepareEnvironment(
SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// 创建环境
ConfigurableEnvironment environment = getOrCreateEnvironment();
// 配置环境
configureEnvironment(environment, applicationArguments.getSourceArgs());
// 发布环境准备事件
listeners.environmentPrepared(environment);
// 绑定环境到此应用
bindToSpringApplication(environment);
// 判断是否需要转换环境
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader())
.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
}
// 附加ConfigurationPropertySource支持到指定环境
ConfigurationPropertySources.attach(environment);
return environment;
}

其中,getOrCreateEnvironment() 方法实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
   private ConfigurableEnvironment getOrCreateEnvironment() {
if (this.environment != null) {
return this.environment;
}
// 根据ClassPath存在的类推断应用运行环境,以下都是web环境
switch (this.webApplicationType) {
case SERVLET:
return new StandardServletEnvironment();
case REACTIVE:
return new StandardReactiveWebEnvironment();
default:
return new StandardEnvironment();
}
}

流程9. 创建ApplicationContext:

createApplicationContext方法实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
   protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
// 1. 初始化并返回org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext Class对象
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
// 忽略异常捕获代码
}
// 2. 调用AnnotationConfigServletWebServerApplicationContext对象的默认构造方法实例化
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}

流程11. 准备应用上下文:

prepareContext方法实现:

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
   private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
// 1. 设置环境
context.setEnvironment(environment);
// 2. 在ApplicationContext中应用任何相关的后置处理,这里为context对象的BeanFactory实例DefaultListableBeanFactory添加转换服务
postProcessApplicationContext(context);
// 3. 在context刷新之前应用实现了ApplicationContextInitializer回调接口的实例进行context上下文对象的初始化
applyInitializers(context);
// 4. 发布context初始化事件
listeners.contextPrepared(context);
// 5. 打印应用版本信息和激活的配置文件信息active profile
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// 6. 添加名称为springApplicationArguments,springBootBanner的单例bean
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
// 7. 加载源(即main方法所在的类对象)不可变的集合对象并注册其bean到应用上下文
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[0]));
// 8. 发布应用准备事件
listeners.contextLoaded(context);
}

应用上下文对象准备好了,接下来就进行刷新上下文操作。

12. 刷新底层的ApplicationContext:

refreshContext方法实现:

1
2
3
4
5
6
7
8
9
10
   private void refreshContext(ConfigurableApplicationContext context) {
refresh(context);
if (this.registerShutdownHook) {
try {
// 向JVM运行时注册一个关机钩子,在JVM关闭时同时关闭这个上下文。
context.registerShutdownHook();
}
......
}
}

进入到ServletWebServerApplicationContext类的refresh(context)方法实现:

1
2
3
4
5
6
7
   @Override
public final void refresh() throws BeansException, IllegalStateException {
try {
super.refresh();
}
......
}

发现是直接调用的父类AbstractApplicationContext的refresh方法实现:

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
   @Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1. 准备好刷新上下文
prepareRefresh();

// 2. 告诉子类刷新内部bean工厂
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// 3. 准备bean工厂以用于此上下文中
prepareBeanFactory(beanFactory);

try {
// 4. 允许在特定的ApplicationContext实现中注册特殊的bean后置处理器
postProcessBeanFactory(beanFactory);

// 5. 实例化并调用所有已注册的BeanFactoryPostProcessor bean
invokeBeanFactoryPostProcessors(beanFactory);

// 6. 实例化并调用所有已注册的BeanPostProcessor bean
registerBeanPostProcessors(beanFactory);

// 7. 初始化MessageSource用于当前上下文,提供参数化和i18n的支持
initMessageSource();

// 8. 初始化事件多路广播用于当前上下文,默认使用SimpleApplicationEventMulticaster单例bean
initApplicationEventMulticaster();

// 9. 在特定上下文子类中初始化其他特殊bean。
onRefresh();

// 10. 检查监听器bean并注册它们
registerListeners();

// 11. 实例化剩余所有非懒加载的单例bean
finishBeanFactoryInitialization(beanFactory);

// 12. 最后一步: 发布相应的事件
finishRefresh();
}
catch (BeansException ex) {
......
// 销毁所有创建的单例来避免悬空资源
destroyBeans();
// 重置 'active' 标识.
cancelRefresh(ex);
// 抛出异常给调用者
throw ex;
}
finally {
// 重置Spring的公共反射元数据缓存
resetCommonCaches();
}
}
}

第一点主要做了以下操作:

  • 清除本地元数据缓存(如果有的话),删除所有缓存的类元数据。
  • 设置其启动日期和活动标志以及执行任何属性源的初始化。

第二点主要做了以下操作:

  • 将成员变量 refreshed 设为 true。
  • 为 DefaultListableBeanFactory 指定一个用于序列化的id。

第三点主要做了以下操作:

  • 配置工厂的标准上下文特征,例如上下文的类加载器和后置处理程序。
  • 所有bean定义都已加载,但还没有实例化bean。

第四点主要做了以下操作:

  • 注册特定应用上下文的后置处理器bean
  • 扫描basePackage指定的包路径
  • 注册被注解的类,例如@Configuration

第五点主要做了以下操作:

  • 实例化并调用所有已注册的BeanFactoryPostProcessor bean,如果给定显式顺序,则遵循显式顺序
  • 分别调用实现了BeanFactoryPostProcessor接口的bean。

第六点主要做了以下操作:

  • 实例化并调用所有已注册的BeanPostProcessor bean,如果给定显式顺序,则遵循显式顺序
  • 分别调用实现了BeanPostProcessor接口的bean。

第九点主要做了以下操作:

  • 默认创建TomcatWebServer
  • 初始化WebApplicationContext和SerlvetContext参数

第十一点完成BeanFactory的初始化并实例化剩余的单例bean:

finishBeanFactoryInitialization方法实现:

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
   protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 初始化用于此上下文的转换服务
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));
}

// 如果没有内嵌value解析器Bean则注册一个(例如 PropertyPlaceholderConfigurer bean),主要用于解析${}占位符.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}

// 尽早地初始化LoadTimeWeaverAware bean以允许尽早地注册其变换器
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}

// 停止正用于类型匹配的临时类加载器
beanFactory.setTempClassLoader(null);

// 缓存所有bean定义的元数据,不接受后面的改变
beanFactory.freezeConfiguration();

// 实例化所有剩余的(非懒加载)单例bean
beanFactory.preInstantiateSingletons();
}

其中重点看最后一步preInstantiateSingletons方法的实现:

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
   @Override
public void preInstantiateSingletons() throws BeansException {
......

// 迭代一个beanDefinitionNames的副本以允许init方法,这些方法又轮流注册新的bean定义。
// 虽然这可能不是常规工厂引导程序的一部分,但它确实可以正常工作。
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

// 触发所有非懒加载单例bean的初始化...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 如果不是抽象的bean并且是非懒加载的单例bean,则进行
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 判断是否是FactoryBean,如果是则进一步判断是否需要尽早的初始化bean,否则直接初始化bean
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}

// 触发所有可用单例bean的afterSingletonsInstantiated方法回调...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}

接下来看getBean(beanName)方法的底层实现,是直接调用doGetBean方法,返回指定bean的实例,该实例可以是共享的或独立的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
   protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 1. 返回bean名称,必要时删除工厂前缀,并将别名解析为规范名称。
final String beanName = transformedBeanName(name);
Object bean;

// 2. 急切地检查单例缓存以手动地注册单例
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
// 3. 判断该当前bean是否在创建中
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 + "'");
}
}
// 4. 获取给定bean实例的对象,如果是FactoryBean,则为bean实例本身或其创建的对象。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

else {
// 其它情况暂不做深入研究,感兴趣的读者可以自行阅读AbstractBeanFactory#doGetBean方法源码
......
}
return (T) bean;
}

查看第二点getSingleton方法的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
   @Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
// 如果从singletonObjects单例bean缓存中获取key为beanName的单例bean为空并且该单例bean
// 当前在创建中(在整个工厂内)则从早期已实例化的单例bean缓存earlySingletonObjects中
// 检查beanName的单例对象,如果为空则进一步从singletonFactories单例工厂缓存中获取beanName为key
// 的BeanFactory,如果BeanFactory不为空则获取到其管理的单例bean实例并将其缓存
// 到earlySingletonObjects对象上,最后从singletonFactories缓存中移除管理该beanName
// 实例的BeanFactory对象(解决循环引用)
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}

几个重要对象说明:

  • singletonObjects:单例bean对象的缓存,ConcurrentHashMap->{beanName:beanInstance}
  • earlySingletonObjects: 早期的单例bean对象的缓存,HashMap->{beanName:beanInstance}
  • singletonFactories:单例BeanFactory的缓存,HashMap->{beanName:beanFactory}, beanFactory->beanInstance

查看第四点getObjectForBeanInstance方法的实现:

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
   protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// bean的name如果以&开头,则是FactoryBean实例
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
// 验证是否是FactoryBean对象,不是则抛出异常
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
}

// 执行到此处,已经得到了bean实例,如果是普通的bean,或者是FacoryBean实例,直接返回.
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}

Object object = null;
if (mbd == null) {
// 从FactoryBeanObjectCache中获取由FactoryBean创建的bean对象
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// beanInstance强转为FactoryBean
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// 如果是单例,则缓存从FactoryBean获取的对象
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 最终调用FactoryBean实例的getObject方法获取bean实例
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}

回到refresh方法的第十二点,最后完成上下文的刷新操作,调用LifecycleProcessor的onRefresh方法并且发布最终的ContextRefreshedEvent事件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
   protected void finishRefresh() {
// 清除此资源加载器中的所有资源缓存。
clearResourceCaches();

// 初始化此上下文的生命周期处理器DefaultLifecycleProcessor。
initLifecycleProcessor();

// 调用DefaultLifecycleProcessor的onRefresh方法
getLifecycleProcessor().onRefresh();

// 发布最终的ContextRefreshedEvent事件
publishEvent(new ContextRefreshedEvent(this));

// 如果激活则参与到LiveBeansView MBean中
LiveBeansView.registerApplicationContext(this);
}

子类finishRefresh方法最后启动相应的WebServer并发布事件。

1
2
3
4
5
6
7
8
   @Override
protected void finishRefresh() {
super.finishRefresh();
WebServer webServer = startWebServer();
if (webServer != null) {
publishEvent(new ServletWebServerInitializedEvent(webServer, this));
}
}

以上就是Spring Boot启动流程源码分析的完整内容,如果有问题欢迎提出!

如果对您有所帮助,欢迎投食!
0%