Spring Boot启动原理深度解析:揭秘背后的秘密

一、Spring Boot简介
Spring Boot是一款开源的Java框架,它简化了Spring应用的初始搭建以及开发过程。Spring Boot利用“约定大于配置”的原则,让开发者可以快速上手,节省了大量的配置时间。本文将深入解析Spring Boot的启动原理,帮助读者更好地理解其工作方式。
二、Spring Boot启动流程
1. 创建Spring Boot应用
首先,我们需要创建一个Spring Boot应用。在Spring Boot 2.x版本中,可以使用Spring Initializr(https://start.spring.io/)快速生成项目。在生成项目时,可以选择所需的依赖,如Spring Web、Spring Data JPA等。
2. 编写主程序
在创建好的项目中,我们需要编写一个主程序,用于启动Spring Boot应用。主程序通常包含一个名为`@SpringBootApplication`的注解,该注解是Spring Boot的核心启动类。
```java
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
```
3. SpringApplication.run()方法
在主程序中,我们调用了`SpringApplication.run()`方法,这是Spring Boot启动的核心。下面将深入解析这个方法的工作原理。
```java
public static ConfigurableApplicationContext run(Class> primarySource, String... args) {
Assert.hasText(args, "Application arguments must not be empty");
return run(primarySource, null, args);
}
```
`run()`方法接收两个参数:`primarySource`和`args`。`primarySource`是启动类,`args`是启动参数。
4. 创建SpringApplication实例
在`run()`方法中,首先创建了一个`SpringApplication`实例。
```java
public static SpringApplication run(Class> primarySource, String[] args) {
return new SpringApplication(primarySource).run(args);
}
```
5. 初始化SpringApplication实例
在创建`SpringApplication`实例后,会调用其构造方法进行初始化。
```java
public SpringApplication(ResourceLoader resourceLoader, Class>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notEmpty(primarySources, "Primary sources must not be empty");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webEnvironment = calculateWebEnvironment();
this.addListeners();
this.addCustomSources();
}
```
在构造方法中,会进行以下操作:
- 设置资源加载器`resourceLoader`。
- 将启动类`primarySource`添加到`primarySources`集合中。
- 判断是否为Web应用,并设置`webEnvironment`。
- 添加监听器。
- 添加自定义源。
6. run()方法执行
在初始化完成后,`SpringApplication`实例会调用`run()`方法。
```java
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
configureHeadlessProperty();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ContextIdSource contextIdSource = new ContextIdSource();
ConfigurableApplicationContext context = createApplicationContext();
analyzers = new FailureAnalyzers(context);
prepareEnvironment(context, applicationArguments);
postProcessEnvironment(context, applicationArguments);
postProcessApplicationContext(context);
context.refresh();
afterRefresh(context, applicationArguments);
stopWatch.stop();
return context;
}
catch (Throwable ex) {
stopWatch.stop();
handleException(context, analyzers, ex);
throw ex;
}
}
```
在`run()`方法中,会进行以下操作:
- 创建`StopWatch`实例,用于计时。
- 创建`ApplicationArguments`实例,用于处理启动参数。
- 创建`ContextIdSource`实例,用于设置上下文ID。
- 创建应用上下文`ConfigurableApplicationContext`。
- 创建`FailureAnalyzers`实例,用于异常分析。
- 配置无头模式。
- 准备环境。
- 处理环境。
- 处理应用上下文。
- 刷新应用上下文。
- 刷新完成后,返回应用上下文。
7. refresh()方法执行
在`run()`方法中,会调用`context.refresh()`方法,这是Spring Boot启动的核心。
```java
public void refresh() throws BeansException {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
}
}
```
在`refresh()`方法中,会进行以下操作:
- 准备刷新。
- 获取并刷新Bean工厂。
- 准备Bean工厂。
- 处理Bean工厂。
- 调用Bean工厂后处理器。
- 注册Bean后处理器。
- 初始化消息源。
- 初始化应用事件多播器。
- 刷新。
- 注册监听器。
- 初始化Bean。
- 完成刷新。
8. Bean加载与初始化
在`refresh()`方法中,会调用`finishBeanFactoryInitialization(beanFactory)`方法,该方法负责加载和初始化Bean。
```java
public void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
if (beanFactory.hasBean("environment")) {
Environment environment = beanFactory.getBean("environment", Environment.class);
if (!environment.isActive()) {
environment.activate();
}
}
beanFactory.preInstantiateSingletons();
}
```
在`finishBeanFactoryInitialization()`方法中,会进行以下操作:
- 获取环境`Environment`。
- 激活环境。
- 预实例化单例Bean。
至此,Spring Boot应用启动完成,可以正常使用。
三、总结
本文深入解析了Spring Boot的启动原理,从创建Spring Boot应用、编写主程序,到`SpringApplication.run()`方法、`refresh()`方法,以及Bean加载与初始化等环节。通过了解这些细节,我们可以更好地理解Spring Boot的工作方式,为后续的开发和应用提供有力支持。






