Spring Boot 启动流程及配置类解析原理

Spring Boot 是一个基于 Spring 框架的开源框架,旨在简化 Spring 应用的配置和部署。通过提供约定优于配置的原则,Spring Boot 大大降低了 Java 企业级应用的开发复杂度。本文将详细介绍 Spring Boot 的启动流程及其配置类的解析原理,帮助开发者深入理解 Spring Boot 的工作机制。

一、Spring Boot 启动流程

1.1 启动入口

Spring Boot 应用的启动入口通常是一个带有 main 方法的类,该类被注解为 @SpringBootApplication。该注解实际上是一个复合注解,包含了以下三个注解:

  • @Configuration:指示该类是一个 Spring 配置类。
  • @EnableAutoConfiguration:启用 Spring Boot 的自动配置机制。
  • @ComponentScan:启用组件扫描,以自动发现并注册 Spring 组件。

以下是一个简单的 Spring Boot 启动类示例:

复制代码
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}
​

1.2 SpringApplication 的启动过程

在 main 方法中,调用了 SpringApplication.run() 方法,该方法是 Spring Boot 应用启动的核心。其主要流程如下:

  1. 创建 SpringApplication 实例 :
    SpringApplication 是启动 Spring Boot 应用的核心类。它负责启动应用的上下文,并执行所有必要的初始化步骤。

    复制代码
    SpringApplication application = new SpringApplication(MyApplication.class);
    ​
  2. 准备上下文 :

    在 run 方法中,首先会准备一个 ApplicationContext(默认是 AnnotationConfigApplicationContext 或 WebApplicationContext),并将主类传入。

  3. 加载配置 :

    根据 @SpringBootApplication 中的设置,加载应用的配置文件(如 application.properties 或 application.yml),并将其转化为配置属性。

  4. 执行自动配置 :

    通过 @EnableAutoConfiguration 注解,Spring Boot 会自动装配必要的组件。例如,如果存在数据库驱动,则自动配置 DataSource。

  5. 启动应用上下文 :

    启动 ApplicationContext,完成 Bean 的初始化和依赖注入。

  6. 触发 ApplicationRunner 和 CommandLineRunner :

    如果定义了 ApplicationRunner 或 CommandLineRunner 接口的实现类,Spring Boot 会在应用启动后自动调用它们。

1.3 SpringApplication.run() 的关键步骤

以下是 SpringApplication.run() 方法中的关键步骤详细解析:

复制代码
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
    SpringApplication application = new SpringApplication(primarySource);
    return application.run(args);
}
​
  1. 构造 SpringApplication 实例 :
    primarySource 是启动类,用于加载上下文。
  2. 准备环境 :
    调用 prepareEnvironment() 方法,设置应用的环境(如 Environment 和 ApplicationArguments)。
  3. 创建应用上下文 :
    调用 createApplicationContext() 方法,根据应用类型创建相应的 ApplicationContext。
  4. 准备上下文 :
    调用 prepareContext() 方法,配置上下文的属性和 Bean。
  5. 刷新上下文 :
    调用 refreshContext() 方法,初始化和刷新上下文。
  6. 调用应用的生命周期事件 :
    触发 ApplicationStartedEvent 和 ApplicationReadyEvent 事件。

1.4 事件机制

在 Spring Boot 启动过程中,会触发多个事件,例如 ApplicationStartedEvent、ApplicationEnvironmentPreparedEvent 和 ApplicationReadyEvent。开发者可以通过实现 ApplicationListener 接口来监听这些事件。

二、Spring Boot 配置类解析原理

2.1 配置类的定义

在 Spring Boot 中,配置类通常是使用 @Configuration 注解标记的类。这些类用于定义 Bean,进行依赖注入和其他配置信息。以下是一个配置类的示例:

复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfig {
    @Bean
    public MyService myService() {
        return new MyService();
    }
}
​

2.2 配置类的解析过程

当 Spring Boot 启动时,配置类的解析过程主要涉及以下步骤:

  1. 组件扫描 :
    在 @SpringBootApplication 注解的类中,会进行组件扫描,寻找所有的 @Configuration 注解。
  2. 创建 ConfigurationClassParser 实例 :
    ConfigurationClassParser 是解析配置类的核心类,负责分析和处理所有的配置类。
  3. 解析配置类 :
    ConfigurationClassParser 会解析配置类中的 @Bean 方法,并生成相应的 BeanDefinition。
  4. 注册 BeanDefinition :
    将解析得到的 BeanDefinition 注册到 BeanDefinitionRegistry 中,供后续使用。

2.3 Bean 的创建与注入

当需要使用某个 Bean 时,Spring 容器会根据 BeanDefinition 创建 Bean 实例,并进行依赖注入。

  1. 获取 BeanDefinition :
    在调用 Bean 的时候,Spring 会从 ApplicationContext 中获取对应的 BeanDefinition。
  2. 实例化 Bean :
    使用 BeanFactory 中的 doGetBean() 方法,创建 Bean 实例。
  3. 依赖注入 :
    Spring 会自动识别 Bean 的依赖关系,进行依赖注入。

2.4 注解的作用

在配置类中,常用的注解包括:

  • @Bean:用于定义 Bean 方法,返回的对象将被注册为 Spring 的 Bean。
  • @Configuration:标识配置类,表示该类可以包含多个 @Bean 方法。
  • @Conditional:用于条件化 Bean 的创建,根据条件决定是否创建 Bean。
相关推荐
Peregrine91 小时前
C++ - > 类和对象
java·c++·算法
一条泥憨鱼1 小时前
【从0开始学习计算机网络】| ARP 协议:地址解析,ARP 欺骗,链路层寻址
网络·后端·学习·计算机网络
2501_933923251 小时前
SpringCloud组件:Eureka服务注册与发现
java·开发语言·后端·spring cloud·eureka
Wang's Blog1 小时前
Java 中间件之 RabbitMQ 快速入门: SpringAMQP 消息转换器
java·中间件·java-rabbitmq
leikooo1 小时前
ARTS 1011: 双堆动态对顶求中位数、IPC 注入与空密码串联接管账户与程序从不做决策
后端
合尘猫1 小时前
AI 项目上线就停:一次事件循环阻塞的完整排查过程
人工智能·后端·python
Re_zero1 小时前
一次 SSE 断流排查:PrintWriter 吞掉了我的 IOException
java·后端
1m555555552 小时前
RAG 工程实战(四):明明召回了正确知识,为什么最终 Top-K 还是漏了?
后端
我是人✓2 小时前
Java核心语法:作用域、循环与大数值处理
java·开发语言·后端
newerp2 小时前
GC Pacer 调优算法:GOGC、GOMEMLIMIT 与容器 OOM 防御
后端·程序员·go