SpringBoot 条件注解的扩展
包路径:org.springframework.boot.autoconfigure.condition
| 注解 | 说明 |
|---|---|
| @ConditionalOnProperty | 根据特定的属性进行条件注入 |
| @ConditionalOnBean | IOC 容器中存在指定的 Bean 进行条件注入 |
| @ConditionalOnMissingBean | IOC 容器中不存在指定的 Bean 进行条件注入 |
| @ConditionalOnClass | JVM 中存在指定的 Class 进行条件注入 |
@ConditionalOnProperty
常用的条件化配置注解,它根据配置文件中的属性值来决定是否创建 Bean 或启用配置。
java
// spring.datasource.type=com.zaxxer.hikari.HikariDataSource 时触发
@Configuration
@ConditionalOnProperty(prefix = "spring.datasource", name = "type", havingValue = "com.zaxxer.hikari.HikariDataSource")
public class FlyHikariDataSourceAutoConfiguration {
private final IDataSourceDecrypt dataSourceDecrypt;
public FlyHikariDataSourceAutoConfiguration(IDataSourceDecrypt dataSourceDecrypt) {
this.dataSourceDecrypt = dataSourceDecrypt;
}
@Bean
@Primary
public FlyHikariDataSourceWrapper hikariDataSourceConfiguration() {
return new FlyHikariDataSourceWrapper(dataSourceDecrypt);
}
}@ConditionalOnBean
基于其他 Bean 的存在与否进行条件化配置的核心注解。它实现了 Bean 之间的依赖关系和条件化创建。
java
// 当某种类型的 Bean 存在时,当 RedissonClient 类型的 Bean 存在时
@Bean
@ConditionalOnBean(RedissonClient.class)
public SlidingWindowRateLimiter slidingWindowRateLimiter(RedissonClient redisson) {
return new SlidingWindowRateLimiter(redisson);
}
// 当某个 Bean 存在时才创建当前 Bean,当 dataSource 存在时
@Bean
@ConditionalOnBean(name = "dataSource")
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
System.out.println("创建JdbcTemplate,因为DataSource存在");
return new JdbcTemplate(dataSource);
}
// 当多个 Bean 都存在时
@Bean
@ConditionalOnBean({DataSource.class, TransactionManager.class})
public TransactionalService transactionalService() {
System.out.println("创建TransactionalService,因为DataSource和TransactionManager都存在");
return new TransactionalService();
}@ConditionalOnMissingBean
用于避免 Bean 重复定义和提供默认实现的核心注解。它检查容器中是否已存在某个 Bean,如果不存在才创建。
java
// 最简单的用法:当指定类型的 Bean 不存在时才创建
@Bean
@ConditionalOnMissingBean // 没有参数,检查当前返回类型
public DataSource dataSource() {
System.out.println("创建默认数据源(因为没有其他 DataSource Bean)");
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.build();
}
// 指定类型:当 DataSource 类型的 Bean 不存在时才创建
// 如果在其他实现了 DataSource 接口,并注册成为 Bean 时将不生效
@Bean
@ConditionalOnMissingBean(DataSource.class)
public DataSource defaultDataSource() {
System.out.println("创建默认 DataSource");
return DataSourceBuilder.create().build();
}
// 指定名称:当指定名称的 Bean 不存在时才创建
// 如果在其他地方创建了名为 customDataSource 的 Bean 时将不生效
@Bean
@ConditionalOnMissingBean(name = "customDataSource")
public DataSource applicationDataSource() {
System.out.println("创建应用数据源(因为 customDataSource 不存在)");
return DataSourceBuilder.create()
.url("jdbc:h2:mem:appdb")
.build();
}
// 多个条件:当多个Bean都不存在时才创建
@Bean
@ConditionalOnMissingBean({DataSource.class, JdbcTemplate.class})
public DatabaseManager databaseManager() {
System.out.println("创建 DatabaseManager(因为 DataSource 和 JdbcTemplate 都不存在)");
return new DatabaseManager();
}@ConditionalOnMissingBean 是 Spring Boot 自动配置的核心,它确保了框架可以提供合理的默认配置,同时允许开发者完全自定义。正确使用这个注解可以大大简化配置,避免冲突,并创建灵活的、可扩展的应用程序架构。
@ConditionalOnClass
根据类路径上是否存在特定类来决定是否创建 Bean 或启用配置的核心注解。它是实现自动配置和条件化依赖的关键。
java
// 最简单的用法:检查单个类是否存在
@Bean
@ConditionalOnClass(name = "redis.clients.jedis.Jedis")
public RedisService redisService() {
System.out.println("创建Redis服务(因为Jedis类存在)");
return new RedisService();
}
// 检查多个类:所有类都存在才创建
@Bean
@ConditionalOnClass({DataSource.class, JdbcTemplate.class})
public DatabaseService databaseService() {
System.out.println("创建数据库服务(DataSource和JdbcTemplate都存在)");
return new DatabaseService();
}
// 使用Class对象(编译时检查)
@Bean
@ConditionalOnClass(Jackson2ObjectMapperBuilder.class)
public ObjectMapper objectMapper() {
System.out.println("创建ObjectMapper(Jackson2ObjectMapperBuilder存在)");
return new ObjectMapper();
}@Profile
用于环境隔离和条件化配置的核心注解。它根据激活的 Profile 来决定是否注册 Bean 或启用配置类。
java
@Bean
@ConditionalOnMissingBean
@Profile({"pro","prod"})
public SmsService smsService() {
SmsServiceImpl smsService = new SmsServiceImpl();
return smsService;
}
@Bean
@ConditionalOnMissingBean
@Profile("dev")
public SmsService mockSmsService() {
MockSmsServiceImpl smsService = new MockSmsServiceImpl();
return smsService;
}
@Bean
@Profile("!prod") // 非生产环境
public SmsService debugService() {
System.out.println("创建调试服务(非生产环境)");
DebugSmsServiceImpl smsService = new DebugSmsServiceImpl();
return smsService;
}
朔风