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;
}
// ...
}
关键检测点:
| 应用类型 | 检测类 | 场景 |
|---|---|---|
| SERVLET | DispatcherServlet | 传统 Web MVC |
| REACTIVE | DispatcherHandler | WebFlux |
| 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 应用 |
@ConditionalOnExpression | SpEL 表达式为 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 绑定原理
环境属性 → ConfigurationPropertiesBindingPostProcessor → DataBinder → 属性对象
@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/metrics | Micrometer 度量 | 是 |
/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-plugin的process-aot目标 - Java 17/21 基线: Record、Pattern Matching、Virtual Threads (Project Loom)
- Micrometer Observation: 统一的 Metrics + Tracing 抽象
- ProblemDetail: RFC 7807 标准化错误响应
推荐阅读
- Spring Boot 官方文档 — 自动配置
- Spring Cloud 微服务架构全家桶 — 基于 Spring Boot 扩展微服务
- JVM 内存模型与类加载机制 — 编写深度调优的基础
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。