springboot

Spring Boot 自动配置原理

By AI-Writer 10 min read

Spring Boot 自动配置原理

Spring Boot 最令人称道的特性是自动配置(Auto Configuration)——你只需引入一个 Starter,整个 Web 服务器、数据源、安全模块就能自动就绪。本文深入剖析这一魔法背后的机制。

@SpringBootApplication 注解组合

三个核心注解

java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
    @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
    @Filter(type = FilterType.CUSTOM,
            classes = AutoConfigurationExcludeFilter.class)
})
public @interface SpringBootApplication {
    // ...
}
  • @SpringBootConfiguration:本质是 @Configuration,表明这是一个配置类
  • @ComponentScan:默认扫描启动类所在包及其子包中的 @Component@Service@Repository@Controller
  • @EnableAutoConfiguration:启用自动配置,这是 Spring Boot 的魔法核心

@EnableAutoConfiguration 详解

java
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    // 指定要排除的自动配置类
    Class<?>[] exclude() default {};

    // 按名称排除
    String[] excludeName() default {};
}

关键在于 AutoConfigurationImportSelector。它实现了 DeferredImportSelector 接口,在 Spring 容器刷新阶段被调用,核心流程如下:

  1. 读取 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件
  2. 解析其中的全限定类名,加载这些自动配置类
  3. 根据 @Conditional* 条件注解判断是否应该生效

自动配置文件的演变

Spring Boot 2.7 之前:spring.factories

plaintext
# META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
  org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration

Spring Boot 2.7 之前使用 META-INF/spring.factories

Spring Boot 3.x:新机制 AutoConfiguration.imports

Spring Boot 3.x 全面迁移到新的自动配置机制:

plaintext
# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
# 每个 Starter 提供一行,不使用反斜杠续行
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

新机制的优势:

  • 按行解析,无需反斜杠续行,格式更清晰
  • 按 Starter 分组,便于维护
  • 支持条件过滤@ConditionalOnClass),缺失依赖时自动跳过

@Conditional 系列条件注解

自动配置类通过 @Conditional* 注解控制生效条件,这是”按需配置”的精髓。

常用条件注解

注解作用
@ConditionalOnClass当 classpath 存在指定类时生效
@ConditionalOnMissingClass当 classpath 不存在指定类时生效
@ConditionalOnBean当容器中存在指定 Bean 时生效
@ConditionalOnMissingBean当容器中不存在指定 Bean 时生效
@ConditionalOnProperty当配置属性满足条件时生效
@ConditionalOnWebApplication当是 Web 应用时生效

一个真实例子

java
// DataSourceAutoConfiguration 部分源码
@AutoConfiguration(
    after = { DataSourceTransactionManagerAutoConfiguration.class,
              HibernateJpaAutoConfiguration.class }
)
@ConditionalOnClass({ DataSource.class, JdbcTemplate.class })
@ConditionalOnProperty(
    prefix = "spring.datasource",
    name = "url",
    matchIfMissing = false  // 如果没有配置 url 则不生效
)
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
    public DataSource dataSource(DataSourceProperties properties) {
        // 创建 DataSource Bean
        return properties.initializeDataSourceBuilder().build();
    }
}

当项目中引入了 spring-boot-starter-data-jpa 时,HikariDataSource 等类存在于 classpath,@ConditionalOnClass 通过,自动配置生效。同时,如果开发者已经手动定义了一个 DataSource Bean,@ConditionalOnMissingBean 生效,Spring Boot 不会覆盖你的定义。

自动配置的执行顺序

@AutoConfigureBefore / @AutoConfigureAfter

java
@AutoConfiguration
@AutoConfigureBefore(JdbcTemplateAutoConfiguration.class)
public class DataSourceAutoConfiguration {
    // 此配置类会在 JdbcTemplateAutoConfiguration 之前执行
}

@AutoConfigureOrder

控制同类配置类之间的相对顺序(数值越小越先执行)。

自定义 Starter

场景

假设你在多个项目中都需要复用一套统一的 JSON 处理逻辑,可以将其封装为一个自定义 Starter。

项目结构

plaintext
my-common-starter/
├── src/main/java/com/example/mystarter/
│   └── MyAutoConfiguration.java
└── src/main/resources/META-INF/
    └── spring/
        └── org.springframework.boot.autoconfigure.AutoConfiguration.imports

自动配置类

java
// MyAutoConfiguration.java
package com.example.mystarter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;

@AutoConfiguration
@ConditionalOnClass(ObjectMapper.class)  // 仅当 classpath 有 ObjectMapper 时生效
public class MyAutoConfiguration {

    @Bean
    @ConditionalOnClass(ObjectMapper.class)
    public ObjectMapper customObjectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JavaTimeModule());  // 注册 Java 8 时间模块
        return mapper;
    }
}

AutoConfiguration.imports

plaintext
# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.example.mystarter.MyAutoConfiguration

消费者使用

xml
<dependency>
    <groupId>com.example</groupId>
    <artifactId>my-common-starter</artifactId>
    <version>1.0.0</version>
</dependency>

引入后,ObjectMapper 就会自动配置好 JavaTimeModule

如何调试自动配置

启用 debug 日志

yaml
# application.yml
debug: true

或启动参数:

bash
java -jar app.jar --debug

输出会显示每个自动配置类的生效状态positive matches / negative matches)。

查看自动配置报告

启动时添加 --debug 后,日志中会打印:

plaintext
=========================
AUTO-CONFIGURATION REPORT
=========================

Positive matches:
-----------------
DataSourceAutoConfiguration matched:
  - @ConditionalOnClass found required class 'javax.sql.DataSource'
  - @ConditionalOnProperty (spring.datasource.url) found property

Negative matches:
------------------
DataSourceAutoConfiguration did not match:
  - @ConditionalOnClass did not find required class 'org.springframework.jdbc.datasource.DriverManagerDataSource'

查看已注册的 Bean

java
@Autowired
ApplicationContext context;

@PostConstruct
public void listBeans() {
    Arrays.stream(context.getBeanDefinitionNames())
          .sorted()
          .forEach(System.out::println);
}

小结

Spring Boot 自动配置的核心机制:

  • AutoConfigurationImportSelector 读取 AutoConfiguration.imports 文件加载配置类
  • @Conditional* 注解根据 classpath、Bean 存在性、配置文件动态判断是否生效
  • 开发者自定义的 Bean 优先级高于自动配置(通过 @ConditionalOnMissingBean 实现)
  • 自定义 Starter 通过标准化的自动配置注册机制实现零配置复用

理解这一机制,你就能在需要时干预配置行为,写出更优雅的 Spring Boot 应用。

#springboot #java #auto-configuration #starter

评论

A

Written by

AI-Writer

Related Articles

springboot
#6

多环境配置与外部化配置

application-&#123;profile&#125;.yml 多环境切换、@ConfigurationProperties 强类型配置绑定、@Value 占位符、配置加密与自定义配置加载顺序

Read More
springboot
#3

依赖注入与 Bean 管理

深入理解 Spring IoC 容器核心概念、@Bean/@Component/@Configuration 注解使用、构造器注入与 Setter 注入、@Autowired 与 @Qualifier 精确注入、Bean 作用域与优先级控制

Read More