01. Spring Boot 核心原理与自动配置

深入 Spring Boot 自动配置原理、Starter 机制、Lifestyle 与条件注解,掌握从零构建企业级应用的底层机制

Spring Boot 通过 约定优于配置 的理念,将传统 Spring 应用繁杂的 XML 配置压缩到几乎为零。但零配置不等于无设计——理解其背后的自动装配、条件判断与生命周期管理,是掌握企业级 Java 开发的必修课。

1. Spring Boot 启动流程全景

main()
  └─ SpringApplication.run()
      ├─ 推断应用类型(Servlet/Reactive/Neither)
      ├─ 加载 BootstrapRegistryInitializer
      ├─ 加载 ApplicationListener(SpringApplicationRunListeners)
      ├─ 准备 Environment(profile、propertySource)
      ├─ 创建 ApplicationContext
      ├─ refreshContext()
      │   ├─ prepareRefresh()
      │   ├─ obtainFreshBeanFactory()
      │   ├─ invokeBeanFactoryPostProcessors()
      │   │   └─ ConfigurationClassPostProcessor ← 核心
      │   ├─ registerBeanPostProcessors()
      │   ├─ onRefresh()
      │   └─ finishRefresh()
      └─ callRunners()

1.1 推断应用类型的依据

// SpringApplication.java
static WebApplicationType deduceFromClasspath() {
    if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", null)
        && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", null)) {
        return WebApplicationType.REACTIVE;
    }
    // ...
}

关键检测点

应用类型检测类场景
SERVLETDispatcherServlet传统 Web MVC
REACTIVEDispatcherHandlerWebFlux
NONE无上述类CLI/后台任务

2. 自动配置核心:@EnableAutoConfiguration

2.1 注解结构

@SpringBootApplication
  ├─ @SpringBootConfiguration    // 等价 @Configuration
  ├─ @EnableAutoConfiguration    // 自动配置入口
     └─ @AutoConfigurationPackage
  └─ @ComponentScan              // 组件扫描

@EnableAutoConfiguration 导入了 AutoConfigurationImportSelector,其核心工作是 META-INF/spring.factories 读取所有自动配置类

2.2 spring.factories 解析

# META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration

加载流程

// AutoConfigurationImportSelector.java
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
    AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
    return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata metadata) {
    List<String> configurations = getCandidateConfigurations(metadata, attributes);
    configurations = removeDuplicates(configurations);
    Set<String> exclusions = getExclusions(metadata, attributes);
    configurations.removeAll(exclusions);
    configurations = getConfigurationClassFilter().filter(configurations);
    fireAutoConfigurationImportEvents(configurations, exclusions);
    return new AutoConfigurationEntry(configurations, exclusions);
}

Spring Boot 2.7+ / 3.x 变更:使用 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 替代 spring.factories

2.3 @Conditional 条件家族

自动配置的灵魂是 条件判断——只有满足条件的 Bean 才会被注册。

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ DataSource.class, JdbcTemplate.class })
@ConditionalOnSingleCandidate(DataSource.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class JdbcTemplateAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean(JdbcOperations.class)
    JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

常用条件注解速查

条件注解匹配行为
@ConditionalOnClass类路径存在指定类
@ConditionalOnMissingClass类路径不存在指定类
@ConditionalOnBean容器中存在指定 Bean
@ConditionalOnMissingBean容器中不存在指定 Bean
@ConditionalOnProperty指定属性满足条件
@ConditionalOnWebApplication是 Web 应用
@ConditionalOnExpressionSpEL 表达式为 true
@ConditionalOnResource资源文件存在

条件评估顺序@AutoConfigureBefore / @AutoConfigureAfter 控制配置类间的加载顺序。

3. Starter 机制揭秘

3.1 Starter = 依赖聚合 + 自动配置

spring-boot-starter-web
  ├─ spring-boot-starter
  │   ├─ spring-boot
  │   ├── spring-boot-autoconfigure
  │   └── spring-boot-starter-logging
  ├─ spring-boot-starter-json
  ├─ spring-boot-starter-tomcat
  └── spring-webmvc

3.2 自定义 Starter 模板

your-spring-boot-starter/
├── pom.xml                         # 引入 autoconfigure 与核心依赖
└── your-spring-boot-autoconfigure/
    ├── pom.xml
    ├── src/main/java/
    │   └── com/example/
    │       ├── MyProperties.java        # @ConfigurationProperties
    │       ├── MyService.java           # 业务服务
    │       └── MyAutoConfiguration.java # 自动配置类
    └── src/main/resources/
        └── META-INF/
            └── spring/
                └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
@Configuration
@EnableConfigurationProperties(MyProperties.class)
public class MyAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean
    public MyService myService(MyProperties properties) {
        return new MyService(properties);
    }
}
# application.properties
your.prefix.name=spring-boot-starter-demo
your.prefix.enabled=true

3.3 @ConfigurationProperties 绑定原理

环境属性 → ConfigurationPropertiesBindingPostProcessorDataBinder → 属性对象

@ConfigurationProperties(prefix = "your.prefix")
@Validated
public class MyProperties {
    @NotNull
    private String name;
    private boolean enabled = true;
    private Duration timeout = Duration.ofSeconds(30); // 具体类型绑定
    // getters & setters
}

4. Bean 注册与生命周期管理

4.1 配置类解析(ConfigurationClassPostProcessor)

@Configuration 类
  ├─ @Import 递归解析
  │   ├─ 普通类 → Bean
  │   ├─ ImportSelector → selectImports()
  │   └─ ImportBeanDefinitionRegistrar → registerBeanDefinitions() ← MyBatis 等用此
  ├─ @ComponentScan → ClassPathBeanDefinitionScanner
  ├─ @Bean 方法 → ConfigurationClassBeanDefinition
  └─ @ImportResource → XML 导入

4.2 Spring Boot 特有的生命周期

// 1. 在 Bean 创建前执行
public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

// 2. 在 Bean 初始化前后执行
public interface BeanPostProcessor {
    Object postProcessBeforeInitialization(Object bean, String beanName);
    Object postProcessAfterInitialization(Object bean, String beanName);
}

// 3. Spring Boot 特有的扩展点
SpringApplicationRunListener    // 启动事件监听
ApplicationRunner / CommandLineRunner  // run() 方法执行后
ApplicationContextInitializer     // Context 创建前

4.3 观察者模式:ApplicationEvent

@Component
public class OrderEventListener {
    @EventListener
    public void handleOrderCreated(OrderCreatedEvent event) {
        // 异步处理 @Async
    }
    
    @EventListener(condition = "#event.amount > 1000")
    public void handleLargeOrder(OrderCreatedEvent event) {
        // 条件监听
    }
}

5. Actuator 与工程化监控

# 暴露所有端点
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
management.metrics.tags.application=${spring.application.name}

核心端点

端点用途敏感
/actuator/health健康检查(磁盘、数据库、自定义)
/actuator/info版本、构建信息
/actuator/metricsMicrometer 度量
/actuator/env环境属性
/actuator/loggers日志级别动态调整
/actuator/threaddump线程 DUMP
/actuator/heapdump堆内存 DUMP

自定义 Health Indicator

@Component
public class RedisHealthIndicator implements HealthIndicator {
    @Override
    public Health health() {
        try {
            redisTemplate.opsForValue().get("health:check");
            return Health.up().withDetail("version", "6.2").build();
        } catch (Exception e) {
            return Health.down(e).build();
        }
    }
}

6. 常见陷阱与最佳实践

反模式正确做法
@ComponentScan 无包路径限定 basePackages 防止加载非预期 Bean
@Configuration 不加别名互相调用proxyBeanMethods = false / 注入依赖而非方法调用
BeanDefinitionOverrideException确认 Starter 是否已提供同名 Bean
条件注解互斥导致 Bean 冲突@Primary / @ConditionalOnProperty 明确优先级
Spring Boot 自动注入的 DataSource自定义时标注 @ConditionalOnMissingBean

7. Spring Boot 3.x 新特性

  • AOT 与 GraalVM 原生镜像: spring-boot-maven-pluginprocess-aot 目标
  • Java 17/21 基线: Record、Pattern Matching、Virtual Threads (Project Loom)
  • Micrometer Observation: 统一的 Metrics + Tracing 抽象
  • ProblemDetail: RFC 7807 标准化错误响应

推荐阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「java-enterprise」更多文章

  1. 限流算法深度解析:令牌桶、漏桶与滑动窗口计数
  2. Java 代码质量:SonarQube、Checkstyle 与 SpotBugs 工程化实践
  3. Spring IoC 容器与依赖注入原理深度剖析