Contents

Spring:SpringBoot 核心原理剖析与实战:从启动流程到自动装配

一、为什么要掌握 SpringBoot 核心原理?

在大多数项目中,SpringBoot 几乎是标配。熟悉它的使用只是“基本功”,理解它的核心机制,才能真正解决下面这些问题:

  • SpringBoot 启动流程里,自动装配是怎么运作的?
  • 启动太慢怎么优化?哪一环卡住了?
  • 自定义 starter 要怎么写才不会和别人的冲突?
  • 自动装配出错怎么精准排查?
  • 为什么某些 Bean 明明写了却没生效?

二、SpringBoot 启动流程全览(执行链路图解)

SpringBoot 应用的启动是由 SpringApplication.run(...) 触发的,下面是一张完整链路简图:

graph TD
A[SpringApplication.run()] --> B[创建 SpringApplication 实例]
B --> C[推断项目类型(web/reactive)]
C --> D[加载所有 SpringApplicationRunListener]
D --> E[准备 Environment 环境变量]
E --> F[创建 ApplicationContext]
F --> G[加载自动配置类、用户配置类]
G --> H[调用 ApplicationRunner / CommandLineRunner]
H --> I[启动完成,可接受请求]

核心步骤解释:

  • 环境准备:解析 application.yml、命令行参数等。
  • 上下文初始化:创建 AnnotationConfigServletWebServerApplicationContext
  • 自动装配生效:扫描所有 @EnableAutoConfiguration 指定的配置类。
  • 启动后回调:执行 ApplicationRunnerCommandLineRunner

三、自动装配的原理与机制解析

Spring Boot 的自动装配依赖于以下机制:

  1. @EnableAutoConfiguration 注解(触发自动装配)
  2. SpringFactories机制(配置类加载)
  3. 条件注解驱动装配逻辑(如 @ConditionalOnClass

1. @EnableAutoConfiguration 注解本质

类路径org.springframework.boot.autoconfigure.EnableAutoConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    ...
}

核心解析:

  • 它本质上是通过 @Import 引入了 AutoConfigurationImportSelector,而这个类会在 Spring 启动时把所有的自动配置类加载进来。

2. AutoConfigurationImportSelector 加载自动配置类

类路径org.springframework.boot.autoconfigure.AutoConfigurationImportSelector

@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
    AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
    List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
    ...
}

✨ 方法说明:

  • getCandidateConfigurations 方法会从 META-INF/spring.factories 中加载所有符合的自动配置类。

📦 3. spring.factories 配置文件

路径位置: 每个 spring-boot-autoconfigure 的 jar 包中 META-INF/spring.factories

# 示例:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
...

加载逻辑:

类路径org.springframework.core.io.support.SpringFactoriesLoader

public static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader) {
    ...
}

这个类会读取所有 jar 包下的 spring.factories 文件,并将 EnableAutoConfiguration 对应的类全都加载进来。


4. 条件注解控制装配行为(如 @ConditionalOnClass)

以 DataSourceAutoConfiguration 为例:

类路径org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

@Configuration
@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class})
@EnableConfigurationProperties(DataSourceProperties.class)
@Import(DataSourceConfiguration.class)
public class DataSourceAutoConfiguration {
    ...
}

注解说明:

  • @ConditionalOnClass:只有当 classpath 中存在 DataSource 类时,才会启用这个配置;
  • @EnableConfigurationProperties:将配置类绑定到 application.yml/properties
  • @Import:引入具体的 DataSource 配置。

5. 配置类注入 Bean 的逻辑(@Bean)

@Bean
@ConditionalOnMissingBean
public DataSource dataSource() {
    ...
}

条件装配机制:

  • @ConditionalOnMissingBean:如果上下文中没有 DataSource 类型的 Bean 才会注册。

自动装配时机分析(源码入口)

Spring Boot 的自动装配是在 refreshContext 之前完成的:

类路径org.springframework.boot.SpringApplication

public ConfigurableApplicationContext run(String... args) {
    ...
    prepareContext(context, environment, listeners, applicationArguments, printedBanner);
    refreshContext(context);
    ...
}

prepareContext → applyInitializers → ConfigurationClassPostProcessor → 自动配置类被注册


总结流程图

@SpringBootApplication
    ↓
@EnableAutoConfiguration
    ↓(@Import)
AutoConfigurationImportSelector
    ↓
读取 spring.factories → 获取自动配置类
    ↓
加载每个 @Configuration 配置类(条件装配)
    ↓
注入各类 Bean(如 DataSource、RedisTemplate 等)

🔍 推荐你深入跟踪的源码类路径索引

作用点类路径方法
自动装配入口EnableAutoConfiguration注解本身
导入配置选择器AutoConfigurationImportSelectorselectImports
factories加载器SpringFactoriesLoaderloadFactories
条件装配注解@ConditionalOnClass, @ConditionalOnMissingBean-
示例配置类DataSourceAutoConfiguration-
Spring Boot 启动流程SpringApplicationrun / prepareContext

四、手写一个自定义 Starter 体验自动装配

Spring Boot 自动装配完整示例:自定义 Starter 教程

本示例目标是手写一个简单的日志输出组件(HelloLog),并实现以下能力:

  • 用户只需引入依赖并配置开关,即可使用日志输出;
  • 自动装配生效与否根据配置控制;
  • 不影响主项目启动流程;
  • 具备完整的可复用性,满足封装业务组件的要求。

Step 1:创建两个模块

模块名说明
hello-log-spring-boot-starterStarter 模块,封装自动装配逻辑
demo-app测试项目,引入 Starter 并验证是否自动装配

Step 2:编写核心业务类

模块:hello-log-spring-boot-starter

1. 业务类 HelloLog.java

package com.example.hellolog;

public class HelloLog {
    private final String prefix;

    public HelloLog(String prefix) {
        this.prefix = prefix;
    }

    public void info(String message) {
        System.out.println("[HelloLog] " + prefix + " " + message);
    }
}

Step 3:编写自动配置类

2. HelloLogProperties.java

package com.example.hellolog;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "hello.log")
public class HelloLogProperties {
    private boolean enabled = true;
    private String prefix = ">>";

    public boolean isEnabled() { return enabled; }
    public void setEnabled(boolean enabled) { this.enabled = enabled; }

    public String getPrefix() { return prefix; }
    public void setPrefix(String prefix) { this.prefix = prefix; }
}

3. HelloLogAutoConfiguration.java

package com.example.hellolog;

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableConfigurationProperties(HelloLogProperties.class)
@ConditionalOnProperty(prefix = "hello.log", name = "enabled", havingValue = "true", matchIfMissing = true)
public class HelloLogAutoConfiguration {

    @Bean
    public HelloLog helloLog(HelloLogProperties props) {
        return new HelloLog(props.getPrefix());
    }
}

Step 4:注册自动配置类

resources/META-INF/spring.factories 文件中添加:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.hellolog.HelloLogAutoConfiguration

Spring Boot 3.x 中使用 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件替代。


Step 5:测试自动装配效果

模块:demo-app

1. 引入 starter 依赖(Maven 示例)

<dependency>
  <groupId>com.example</groupId>
  <artifactId>hello-log-spring-boot-starter</artifactId>
  <version>1.0.0</version>
</dependency>

2. 配置 application.yml

hello:
  log:
    enabled: true
    prefix: "[DEMO]"

3. 编写控制器

@RestController
public class HelloController {

    @Autowired
    private HelloLog helloLog;

    @GetMapping("/test")
    public String testLog() {
        helloLog.info("你好,自动装配!");
        return "log printed";
    }
}

核心机制回顾

环节技术点
启用配置@EnableConfigurationProperties 自动绑定配置项
条件控制@ConditionalOnProperty 控制是否启用配置类
注册配置spring.factories 声明配置类被 SpringBoot 加载
自动注入自动注册为 Bean,被主项目注入使用

五、常见问题定位思路

问题排查建议
自动配置类没生效是否在 spring.factories 注册了?是否条件注解被过滤?
Bean 冲突是否使用了 @ConditionalOnMissingBean?是否注入了多个同类 Bean?
启动慢打开 debug=true 查看自动装配类加载情况

六、总结与延伸

SpringBoot 的底层逻辑其实非常“Spring”,自动装配并不是黑魔法,而是大量 @Conditional 组合起来的精妙设计。

理解 SpringBoot 的启动链路与装配机制,不但有助于性能调优与组件开发,更能让你在架构升级、故障排查中如鱼得水。