一、什么是自动配置?
1. 定义
自动配置:Spring Boot 根据项目中的依赖和配置,自动装配所需的 Bean,减少手动配置的工作量。
2. 对比:传统 Spring vs Spring Boot
传统 Spring 配置(繁琐)
java
@Configuration
public class DataSourceConfig {
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("root");
dataSource.setPassword("password");
return dataSource;
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
DataSource dataSource) {
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setDataSource(dataSource);
factory.setPackagesToScan("com.example.myapp.model");
factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
return factory;
}
@Bean
public PlatformTransactionManager transactionManager(
EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
Spring Boot 自动配置(简洁)
只需要一个依赖:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
配置文件(application.properties):
properties
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=password
自动配置完成!无需写任何 Java 配置代码。
3. 自动配置的核心价值
| 传统 Spring | Spring Boot |
|---|---|
| 手动创建 Bean | 自动创建 Bean |
| 大量重复配置 | 约定优于配置 |
| 配置分散 | 配置集中 |
| 学习成本高 | 快速上手 |
二、自动配置的工作原理
1. 核心流程图
less
启动应用 (@SpringBootApplication)
↓
扫描 classpath 下的依赖
↓
加载自动配置类 (META-INF/spring.factories 或 spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports)
↓
根据条件注解 (@Conditional) 决定是否创建 Bean
↓
应用用户自定义配置
↓
完成 Bean 装配
2. @SpringBootApplication 注解
java
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
@SpringBootApplication 是一个组合注解:
java
@SpringBootConfiguration // 标记为配置类
@EnableAutoConfiguration // 启用自动配置(核心)
@ComponentScan // 扫描组件(@Component、@Service 等)
public @interface SpringBootApplication {
// ...
}
3. @EnableAutoConfiguration 注解
java
@Import(AutoConfigurationImportSelector.class) // 导入自动配置选择器
public @interface EnableAutoConfiguration {
// ...
}
AutoConfigurationImportSelector 的工作:
- 读取
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports - 加载所有自动配置类
- 根据条件注解过滤不需要的配置
4. 自动配置类的发现机制
Spring Boot 2.7 之前
文件位置: META-INF/spring.factories
properties
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
...
Spring Boot 2.7 及之后
文件位置: META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
erlang
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration
...
三、条件注解(@Conditional)
1. 什么是条件注解?
条件注解:根据特定条件决定是否创建 Bean 或加载配置。
2. 常用条件注解
| 注解 | 作用 | 示例 |
|---|---|---|
@ConditionalOnClass |
classpath 中存在指定类时生效 | @ConditionalOnClass(DataSource.class) |
@ConditionalOnMissingClass |
classpath 中不存在指定类时生效 | @ConditionalOnMissingClass(RedisTemplate.class) |
@ConditionalOnBean |
Spring 容器中存在指定 Bean 时生效 | @ConditionalOnBean(DataSource.class) |
@ConditionalOnMissingBean |
Spring 容器中不存在指定 Bean 时生效 | @ConditionalOnMissingBean(DataSource.class) |
@ConditionalOnProperty |
配置文件中满足指定属性时生效 | @ConditionalOnProperty(name="app.cache.enabled", havingValue="true") |
@ConditionalOnResource |
存在指定资源文件时生效 | @ConditionalOnResource(resources="classpath:application.properties") |
@ConditionalOnWebApplication |
是 Web 应用时生效 | @ConditionalOnWebApplication |
@ConditionalOnNotWebApplication |
不是 Web 应用时生效 | @ConditionalOnNotWebApplication |
3. 条件注解示例
示例 1:@ConditionalOnClass
场景:只有引入 MySQL 驱动时,才创建 DataSource
java
@Configuration
@ConditionalOnClass(DataSource.class) // classpath 中存在 DataSource 类
public class DataSourceAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 用户没有自定义 DataSource
public DataSource dataSource() {
// 创建默认 DataSource
return new DriverManagerDataSource();
}
}
示例 2:@ConditionalOnProperty
场景:根据配置决定是否启用缓存
java
@Configuration
@ConditionalOnProperty(
prefix = "cache", // 配置前缀
name = "enabled", // 配置名称
havingValue = "true", // 匹配的值
matchIfMissing = false // 默认不启用
)
public class CacheAutoConfiguration {
@Bean
public CacheManager cacheManager() {
// 创建缓存管理器
return new ConcurrentMapCacheManager();
}
}
配置文件:
properties
cache.enabled=true # 启用缓存
示例 3:@ConditionalOnBean
场景:只有 DataSource 存在时,才创建 JdbcTemplate
java
@Configuration
public class JdbcTemplateAutoConfiguration {
@Bean
@ConditionalOnBean(DataSource.class) // DataSource 存在时才创建
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}
示例 4:@ConditionalOnMissingBean
场景:用户没有自定义时,使用默认实现
java
@Configuration
public class MyServiceAutoConfiguration {
@Bean
@ConditionalOnMissingBean(MyService.class) // 用户没有自定义 MyService
public MyService myService() {
// 返回默认实现
return new DefaultMyService();
}
}
用户自定义实现:
java
@Configuration
public class CustomConfig {
@Bean
public MyService myService() {
// 自定义实现(优先级高于默认实现)
return new CustomMyService();
}
}
四、DataSource 自动配置案例分析
1. 自动配置类
java
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(DataSource.class) // classpath 中存在 DataSource 类
@ConditionalOnMissingBean(DataSource.class) // 用户没有自定义 DataSource
@EnableConfigurationProperties(DataSourceProperties.class) // 绑定配置属性
@Import(DataSourcePoolMetadataProvidersConfiguration.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
public class DataSourceAutoConfiguration {
// 嵌入式数据库配置(H2)
@Configuration(proxyBeanMethods = false)
@Conditional(EmbeddedDatabaseCondition.class)
@ConditionalOnMissingBean(DataSource.class)
@Import(EmbeddedDataSourceConfiguration.class)
protected static class EmbeddedDatabaseConfiguration {
}
// 池化数据源配置(HikariCP、Tomcat、Dbcp2)
@Configuration(proxyBeanMethods = false)
@Conditional(PooledDataSourceCondition.class)
@ConditionalOnMissingBean(DataSource.class)
@Import({ DataSourceConfiguration.Hikari.class,
DataSourceConfiguration.Tomcat.class,
DataSourceConfiguration.Dbcp2.class,
DataSourceConfiguration.OracleUcp.class,
DataSourceConfiguration.Generic.class })
protected static class PooledDataSourceConfiguration {
}
}
2. 配置属性绑定
DataSourceProperties.java:
java
@ConfigurationProperties(prefix = "spring.datasource") // 绑定 spring.datasource.* 配置
public class DataSourceProperties {
private String url;
private String username;
private String password;
private String driverClassName;
// getter/setter
}
配置文件:
properties
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
3. HikariCP 自动配置
java
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(HikariDataSource.class) // classpath 中存在 HikariDataSource
@ConditionalOnMissingBean(DataSource.class) // 用户没有自定义 DataSource
@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource", matchIfMissing = true)
static class Hikari {
@Bean
HikariDataSource dataSource(DataSourceProperties properties) {
// 创建 HikariDataSource
return createDataSource(properties, HikariDataSource.class);
}
}
五、自动配置优先级
1. 配置优先级(从高到低)
markdown
1. @Bean 方法中的显式配置
2. application-{profile}.properties/yml
3. application.properties/yml
4. 自动配置类的默认值
2. 示例:DataSource 配置优先级
场景 1:用户显式配置(最高优先级)
java
@Configuration
public class CustomDataSourceConfig {
@Bean
public DataSource dataSource() {
// 用户自定义 DataSource(优先级最高)
return new CustomDataSource();
}
}
场景 2:配置文件
properties
# application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/customdb
spring.datasource.username=admin
spring.datasource.password=secret
场景 3:自动配置(最低优先级)
java
@Configuration
@ConditionalOnMissingBean(DataSource.class) // 用户没有配置时才生效
public class DataSourceAutoConfiguration {
@Bean
public DataSource dataSource() {
// 自动配置的默认值
return new DriverManagerDataSource();
}
}
六、自定义自动配置
1. 创建自动配置类
MyServiceAutoConfiguration.java:
java
@Configuration
@ConditionalOnClass(MyService.class) // classpath 中存在 MyService
@EnableConfigurationProperties(MyServiceProperties.class) // 绑定配置
public class MyServiceAutoConfiguration {
@Bean
@ConditionalOnMissingBean(MyService.class) // 用户没有自定义时才创建
public MyService myService(MyServiceProperties properties) {
MyService service = new MyService();
service.setEnabled(properties.isEnabled());
service.setCacheSize(properties.getCacheSize());
return service;
}
}
2. 创建配置属性类
MyServiceProperties.java:
java
@ConfigurationProperties(prefix = "myapp.service") // 绑定 myapp.service.* 配置
public class MyServiceProperties {
private boolean enabled = true; // 默认启用
private int cacheSize = 100; // 默认缓存大小
// getter/setter
}
3. 注册自动配置
文件位置: META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.example.myapp.autoconfigure.MyServiceAutoConfiguration
4. 使用自定义自动配置
配置文件:
properties
myapp.service.enabled=true
myapp.service.cache-size=200
代码中使用:
java
@Service
public class UserService {
@Autowired
private MyService myService; // 自动注入
public void doSomething() {
if (myService.isEnabled()) {
// 使用 MyService
}
}
}
七、禁用自动配置
1. 全局禁用自动配置
java
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class, // 禁用 DataSource 自动配置
RedisAutoConfiguration.class // 禁用 Redis 自动配置
})
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
2. 通过配置文件禁用
application.properties:
properties
spring.autoconfigure.exclude=\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
3. 条件禁用
通过条件注解:
properties
myapp.cache.enabled=false # 禁用缓存自动配置
八、调试自动配置
1. 启用调试模式
application.properties:
properties
debug=true
启动日志输出:
markdown
============================
CONDITIONS EVALUATION REPORT
============================
Positive matches: # 满足条件的自动配置
-----------------
DataSourceAutoConfiguration matched:
- @ConditionalOnClass found required class 'javax.sql.DataSource' (OnClassCondition)
MyServiceAutoConfiguration matched:
- @ConditionalOnClass found required class 'com.example.MyService' (OnClassCondition)
Negative matches: # 不满足条件的自动配置
-----------------
RedisAutoConfiguration did not match:
- @ConditionalOnClass did not find required class 'org.springframework.data.redis.connection.RedisConnectionFactory' (OnClassCondition)
Exclusions: # 手动排除的自动配置
-----------
None
Unconditional classes: # 无条件自动配置
----------------------
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
2. 使用 Actuator 查看自动配置
添加依赖:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
配置文件:
properties
management.endpoints.web.exposure.include=*
访问自动配置报告:
bash
curl http://localhost:8080/actuator/conditions
3. 使用 IDE 查看自动配置
IntelliJ IDEA:
- 打开
Run/Debug Configurations - 勾选
Enable launch optimization - 启动应用后,在控制台查看自动配置报告
九、最佳实践
1. 理解约定优于配置
| 约定 | 说明 |
|---|---|
| 默认端口 | 8080 |
| 配置文件 | application.properties/yml |
| 静态资源目录 | src/main/resources/static |
| 模板目录 | src/main/resources/templates |
| 测试目录 | src/test/java |
2. 合理使用自动配置
| 场景 | 建议 |
|---|---|
| 快速开发 | 使用自动配置 |
| 定制化需求 | 自定义配置(优先级高于自动配置) |
| 不需要的功能 | 禁用自动配置 |
| 学习调试 | 启用 debug 模式 |
3. 避免过度依赖自动配置
问题:
- 不了解底层原理
- 遇到问题难以排查
- 定制化需求无法满足
解决方案:
- 理解自动配置原理
- 使用 debug 模式调试
- 必要时自定义配置
十、总结
| 概念 | 说明 |
|---|---|
| 自动配置 | 根据依赖和配置自动装配 Bean |
| @SpringBootApplication | 组合注解(@SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan) |
| 条件注解 | 根据条件决定是否加载配置(@ConditionalOnClass、@ConditionalOnProperty 等) |
| 配置优先级 | @Bean > application-{profile} > application > 自动配置 |
| 禁用自动配置 | @SpringBootApplication(exclude = {...}) 或 spring.autoconfigure.exclude |
| 调试自动配置 | debug=true 或 Actuator /actuator/conditions |