共计 3625 个字符,预计需要花费 10 分钟才能阅读完成。
作者在最近的技术论坛里看到关于Spring Boot自动装配相关内容,对这块了解不是很深入,故写一篇文章总结一下Spring Boot的自动装配机制。
本文适合希望深入理解 Spring Boot 自动装配机制,并需要对默认自动装配行为进行控制、重写或精细化替换的开发者阅读。
背景:为什么要禁用自动装配?
Spring Boot 的核心特性之一是“约定优于配置”,也就是它通过自动装配(AutoConfiguration)机制,帮助我们快速构建系统。例如:
- Redis 自动注册
RedisTemplate
; - 数据源自动注册
DataSource
; - Elasticsearch 自动注册客户端等。
虽然自动装配极大提高了开发效率,但它并非万能。某些场景下,默认配置并不符合实际业务需求,比如:
场景 | 说明 |
---|---|
Redis 使用自定义 JSON 序列化 | Spring Boot 默认使用 JDK 序列化,效率低 |
数据源使用多库动态切换 | Spring Boot 默认只支持单数据源 |
RabbitMQ 需要手动声明队列/交换机绑定 | 官方自动配置类未覆盖业务需求 |
Redis Sentinel 集群连接超时调优 | 自动配置过于保守,难以定制 |
一、Spring Boot 自动装配底层机制简述
理解禁用之前,必须清楚自动装配的触发机制。
✅ 核心注解:@EnableAutoConfiguration
它通常被组合在 @SpringBootApplication
注解中:
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
展开后,相当于:
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Lijuanjuan { ... }
✅ 它如何起作用?
@EnableAutoConfiguration
会触发AutoConfigurationImportSelector
;- 它读取
META-INF/spring.factories
文件中配置的所有自动配置类; - Spring Boot 会判断每个自动配置类是否应该生效(基于类是否存在、配置条件、环境条件等);
- 满足条件的自动配置类会被注册为 Bean。
例如 Redis 的自动配置:
# spring-boot-autoconfigure-X.X.X.jar
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
...
二、如何禁用自动装配类?
1. 方法一:通过 exclude
属性排除自动配置类(推荐)
@SpringBootApplication(
exclude = {
RedisAutoConfiguration.class,
DataSourceAutoConfiguration.class
}
)
public class Lijj {}
适合用于全局禁用,最安全、最直观的方式。
2. 方法二:使用 @EnableAutoConfiguration(exclude = ...)
适合在非主启动类中,局部禁用部分自动装配类:
@Configuration
@EnableAutoConfiguration(exclude = {RedisAutoConfiguration.class})
public class RedisConfig {}
3. 方法三:配置文件关闭(部分模块支持)
spring:
redis:
enabled: false
注意:这种方式并非通用,仅当 starter 明确支持该开关时可用。例如:
@ConditionalOnProperty(prefix = "spring.redis", name = "enabled", havingValue = "true", matchIfMissing = true)
4. 方法四:实现 AutoConfigurationImportFilter
进行动态筛选(高级)
可用于组合判断、条件控制:
public class MyAutoConfigurationImportFilter implements AutoConfigurationImportFilter {
@Override
public boolean[] match(String[] classNames, AutoConfigurationMetadata metadata) {
boolean[] result = new boolean[classNames.length];
for (int i = 0; i < classNames.length; i++) {
if ("org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration"
.equals(classNames[i])) {
result[i] = false;
} else {
result[i] = true;
}
}
return result;
}
}
并在 resources/META-INF/spring.factories
中配置:
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
com.lijj.MyAutoConfigurationImportFilter
优势:
- 可以结合业务配置动态控制是否启用自动装配;
- 支持按环境、按租户条件过滤;
- 避免硬编码
exclude
列表。
三、替换自动配置的正确姿势:自定义配置类
禁用自动配置之后,你就可以完全掌控 Bean 的注入过程,例如(以Redis为例):
@Configuration
public class CustomRedisConfiguration {
// 可以自行选择Redis连接池,序列化方式等
@Bean
public RedisConnectionFactory redisConnectionFactory() {
LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
.commandTimeout(Duration.ofSeconds(5))
.shutdownTimeout(Duration.ZERO)
.build();
RedisStandaloneConfiguration serverConfig = new RedisStandaloneConfiguration();
serverConfig.setHostName("localhost");
serverConfig.setPort(6379);
return new LettuceConnectionFactory(serverConfig, clientConfig);
}
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 使用 Jackson2 序列化替代 JDK 序列化
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer =
new Jackson2JsonRedisSerializer<>(Object.class);
template.setDefaultSerializer(jackson2JsonRedisSerializer);
return template;
}
}
四、常见自动配置类一览
模块 | 自动配置类 |
---|---|
Redis | RedisAutoConfiguration |
MySQL | DataSourceAutoConfiguration |
RabbitMQ | RabbitAutoConfiguration |
JPA | HibernateJpaAutoConfiguration |
Elasticsearch | ElasticsearchAutoConfiguration |
Kafka | KafkaAutoConfiguration |
Web MVC | WebMvcAutoConfiguration |
注:可在 spring-boot-autoconfigure-*.jar
包内的 META-INF/spring.factories
中查看完整列表。
如果本文对你有帮助,欢迎点赞、评论、收藏!我是 李卷卷,专注Java相关知识输出。感谢阅读!
正文完