SpringBoot启动过程的实现

2025-05-29 0 57

SpringBoot启动过程分析,首先打开SpringBoot的启用入口Main类:

?

1

2

3

4

5

6
@SpringBootApplication

public class ApplicationMain{

public static void main(String[] args) {

SpringApplication.run(ApplicationMain.class, args);

}

}

可以看到main方法里面只有一行核心启用类:SpringApplication.run(ApplicationMain.class, args);这个是关键,在改行打上断点,debug模式启动该main类。点击下一步进入SpringApplication的源码对应的run方法:

?

1

2

3
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {

return (new SpringApplication(sources)).run(args);

}

初始化SpringApplication

SpringApplication实例化之前会调用构造方法进行初始化:

?

1

2

3

4

5

6

7

8

9
public SpringApplication(Object... sources) {

this.bannerMode = Mode.CONSOLE;

this.logStartupInfo = true;

this.addCommandLineProperties = true;

this.headless = true;

this.registerShutdownHook = true;

this.additionalProfiles = new HashSet();

this.initialize(sources);

}

而SpringApplication构造方法的核心是:this.initialize(sources);初始化方法,SpringApplication通过调用该方法来初始化。

?

1

2

3

4

5

6

7

8

9

10
private void initialize(Object[] sources) {

if (sources != null && sources.length > 0) {

this.sources.addAll(Arrays.asList(sources));

}

this.webEnvironment = deduceWebEnvironment();

setInitializers((Collection) getSpringFactoriesInstances(

ApplicationContextInitializer.class));

setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));

this.mainApplicationClass = deduceMainApplicationClass();

}

1.deduceWebEnvironment方法是用来判断当前应用的环境,该方法通过获取这两个类来判断当前环境是否是web环境,如果能获得这两个类说明是web环境,否则不是。

?

1

2
javax.servlet.Servlet

org.springframework.web.context.ConfigurableWebApplicationContext

2.getSpringFactoriesInstances方法主要用来从spring.factories文件中找出key为ApplicationContextInitializer的类并实例化,然后调用setInitializers方法设置到SpringApplication的initializers属性中。这个过程就是找出所有的应用程序初始化器。

?

1

2

3

4

5

6

7
private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));

List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);

AnnotationAwareOrderComparator.sort(instances);

return instances;

}

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {

String factoryClassName = factoryClass.getName();

try {

//从spring.factories文件中找出key为ApplicationContextInitializer的类

Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");

ArrayList result = new ArrayList();

while(urls.hasMoreElements()) {

URL url = (URL)urls.nextElement();

Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));

String factoryClassNames = properties.getProperty(factoryClassName);

result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));

}

return result;

} catch (IOException var8) {

throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + "] factories from location [" + "META-INF/spring.factories" + "]", var8);

}

}

当前的初始化器有如下几个:

SpringBoot启动过程的实现

3.同理调用getSpringFactoriesInstances从spring.factories文件中找出key为ApplicationListener的类并实例化,然后调用setListeners方法设置到SpringApplication的listeners属性中。这个过程就是找出所有的应用程序事件监听器。
当前的事件监听器有如下几个:

SpringBoot启动过程的实现

4.调用deduceMainApplicationClass方法找出main类,就是这里的ApplicationMain类。

运行SpringApplication

初始化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
public ConfigurableApplicationContext run(String... args) {

//计时器,统计任务的执行时间

StopWatch stopWatch = new StopWatch();

//开始执行

stopWatch.start();

ConfigurableApplicationContext context = null;

FailureAnalyzers analyzers = null;

this.configureHeadlessProperty();

// 获取SpringApplicationRunListeners启动事件监听器,这里只有一个EventPublishingRunListener

SpringApplicationRunListeners listeners = this.getRunListeners(args);

// 封装成SpringApplicationEvent事件然后广播出去给SpringApplication中的listeners所监听

listeners.starting();

try {

// 构造一个应用程序参数持有类

ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

// 准备并配置环境

ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);

// 打印banner图形

Banner printedBanner = this.printBanner(environment);

// 创建Spring容器

context = this.createApplicationContext();

new FailureAnalyzers(context);

// 配置Spring容器

this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);

// 容器上下文刷新

this.refreshContext(context);

// 容器创建完成之后调用afterRefresh方法

this.afterRefresh(context, applicationArguments);

// 调用监听器,广播Spring启动结束的事件

listeners.finished(context, (Throwable)null);

// 停止计时器

stopWatch.stop();

if (this.logStartupInfo) {

(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);

}

return context;

} catch (Throwable var9) {

this.handleRunFailure(context, listeners, (FailureAnalyzers)analyzers, var9);

throw new IllegalStateException(var9);

}

}

SpringApplicationRunListeners

1.获取启动事件监听器,可以看看该方法:

SpringApplicationRunListeners listeners = this.getRunListeners(args);

?

1

2

3

4
private SpringApplicationRunListeners getRunListeners(String[] args) {

Class<?>[] types = new Class[]{SpringApplication.class, String[].class};

return new SpringApplicationRunListeners(logger, this.getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));

}

同样的通过调用getSpringFactoriesInstances方法去META-INF/spring.factories文件中拿到SpringApplicationRunListener监听器,当前的SpringApplicationRunListener事件监听器只有一个EventPublishingRunListener广播事件监听器:

SpringBoot启动过程的实现

SpringApplicationRunListeners内部持有SpringApplicationRunListener集合和1个Log日志类。用于SpringApplicationRunListener监听器的批量执行。

SpringApplicationRunListener用于监听SpringApplication的run方法的执行,它定义了5个步骤:

1.starting:run方法执行的时候立马执行,对应的事件类型是ApplicationStartedEvent
2.environmentPrepared:ApplicationContext创建之前并且环境信息准备好的时候调用,对应的事件类型是ApplicationEnvironmentPreparedEvent
3.contextPrepared:ApplicationContext创建好并且在source加载之前调用一次,没有具体的对应事件
4.contextLoaded:ApplicationContext创建并加载之后并在refresh之前调用,对应的事件类型是ApplicationPreparedEvent
5.finished:run方法结束之前调用,对应事件的类型是ApplicationReadyEvent或ApplicationFailedEvent

SpringApplicationRunListener目前只有一个实现类EventPublishingRunListener,详见获取SpringApplicationRunListeners。它把监听的过程封装成了SpringApplicationEvent事件并让内部属性ApplicationEventMulticaster接口的实现类SimpleApplicationEventMulticaster广播出去,广播出去的事件对象会被SpringApplication中的listeners属性进行处理。

所以说SpringApplicationRunListener和ApplicationListener之间的关系是通过ApplicationEventMulticaster广播出去的SpringApplicationEvent所联系起来的

2.启动事件监听器

通过listeners.starting()可以启动事件监听器SpringApplicationRunListener ,SpringApplicationRunListener 是一个启动事件监听器接口:

?

1

2

3

4

5

6

7

8

9

10

11
public interface SpringApplicationRunListener {

void starting();

void environmentPrepared(ConfigurableEnvironment var1);

void contextPrepared(ConfigurableApplicationContext var1);

void contextLoaded(ConfigurableApplicationContext var1);

void finished(ConfigurableApplicationContext var1, Throwable var2);

}

SpringApplicationRunListener 接口的具体实现就是EventPublishingRunListener类,我们主要来看一下它的startting方法,该方法会封装成SpringApplicationEvent事件然后广播出去给SpringApplication中的listeners所监听。

?

1

2

3
public void starting() {

this.initialMulticaster.multicastEvent(new ApplicationStartedEvent(this.application, this.args));

}

配置并准备环境

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16
private ConfigurableEnvironment prepareEnvironment(

SpringApplicationRunListeners listeners,

ApplicationArguments applicationArguments) {

// 创建应用程序的环境信息。如果是web程序,创建StandardServletEnvironment;否则,创建StandardEnvironment

ConfigurableEnvironment environment = getOrCreateEnvironment();

// 配置环境信息。比如profile,命令行参数

configureEnvironment(environment, applicationArguments.getSourceArgs());

// 广播出ApplicationEnvironmentPreparedEvent事件给相应的监听器执行

listeners.environmentPrepared(environment);

// 环境信息的校对

if (!this.webEnvironment) {

environment = new EnvironmentConverter(getClassLoader())

.convertToStandardEnvironmentIfNecessary(environment);

}

return environment;

}

判断环境,如果是web程序,创建StandardServletEnvironment;否则,创建StandardEnvironment。

?

1

2

3

4

5

6

7
private ConfigurableEnvironment getOrCreateEnvironment() {

if (this.environment != null) {

return this.environment;

} else {

return (ConfigurableEnvironment)(this.webEnvironment ? new StandardServletEnvironment() : new StandardEnvironment());

}

}

创建Spring容器上下文

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18
protected ConfigurableApplicationContext createApplicationContext() {

Class<?> contextClass = this.applicationContextClass;

if (contextClass == null) {

try {

// 判断是否是web应用,

// 如果是则创建AnnotationConfigEmbeddedWebApplicationContext,否则创建AnnotationConfigApplicationContext

contextClass = Class.forName(this.webEnvironment

? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);

}

catch (ClassNotFoundException ex) {

throw new IllegalStateException(

"Unable create a default ApplicationContext, "

+ "please specify an ApplicationContextClass",

ex);

}

}

return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);

}

配置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
private void prepareContext(ConfigurableApplicationContext context,

ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,

ApplicationArguments applicationArguments, Banner printedBanner) {

// 设置Spring容器上下文的环境信息

context.setEnvironment(environment);

// Spring容器创建之后做一些额外的事

postProcessApplicationContext(context);

// SpringApplication的初始化器开始工作

applyInitializers(context);

// 遍历调用SpringApplicationRunListener的contextPrepared方法。目前只是将这个事件广播器注册到Spring容器中

listeners.contextPrepared(context);

if (this.logStartupInfo) {

logStartupInfo(context.getParent() == null);

logStartupProfileInfo(context);

}

// 把应用程序参数持有类注册到Spring容器中,并且是一个单例

context.getBeanFactory().registerSingleton("springApplicationArguments",

applicationArguments);

if (printedBanner != null) {

context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);

}

// 加载sources,sources是main方法所在的类

Set<Object> sources = getSources();

Assert.notEmpty(sources, "Sources must not be empty");

// 将sources加载到应用上下文中。最终调用的是AnnotatedBeanDefinitionReader.registerBean方法

load(context, sources.toArray(new Object[sources.size()]));

// 广播出ApplicationPreparedEvent事件给相应的监听器执行

// 执行EventPublishingRunListener.contextLoaded方法

listeners.contextLoaded(context);

}

Spring容器创建之后回调方法postProcessApplicationContext

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {

// 如果SpringApplication设置了实例命名生成器,则注册到Spring容器中

if (this.beanNameGenerator != null) {

context.getBeanFactory().registerSingleton(

AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,

this.beanNameGenerator);

}

// 如果SpringApplication设置了资源加载器,设置到Spring容器中

if (this.resourceLoader != null) {

if (context instanceof GenericApplicationContext) {

((GenericApplicationContext) context)

.setResourceLoader(this.resourceLoader);

}

if (context instanceof DefaultResourceLoader) {

((DefaultResourceLoader) context)

.setClassLoader(this.resourceLoader.getClassLoader());

}

}

}

初始化器开始工作

?

1

2

3

4

5

6

7

8

9
protected void applyInitializers(ConfigurableApplicationContext context) {

// 遍历每个初始化器,调用对应的initialize方法

for (ApplicationContextInitializer initializer : getInitializers()) {

Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(

initializer.getClass(), ApplicationContextInitializer.class);

Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");

initializer.initialize(context);

}

}

Spring容器创建完成之后会调用afterRefresh方法

ApplicationRunner、CommandLineRunner类都是在在afterRefresh方法中调用的,也就是说在Spring容器创建之后执行的。

?

1

2

3

4

5

6

7

8

9
protected void applyInitializers(ConfigurableApplicationContext context) {

// 遍历每个初始化器,调用对应的initialize方法

for (ApplicationContextInitializer initializer : getInitializers()) {

Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(

initializer.getClass(), ApplicationContextInitializer.class);

Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");

initializer.initialize(context);

}

}

参考:https://blog.wangqi.love/articles/Spring/SpringBoot启动过程.html

到此这篇关于SpringBoot启动过程的实现的文章就介绍到这了,更多相关SpringBoot启动过程内容请搜索快网idc以前的文章或继续浏览下面的相关文章希望大家以后多多支持快网idc!

原文链接:https://blog.csdn.net/chengbinbbs/article/details/88557162

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 SpringBoot启动过程的实现 https://www.kuaiidc.com/117582.html

相关文章

发表评论
暂无评论