在 Spring 应用开发中,条件化 Bean 注册是配置灵活性的关键一环。@Profile
和 @Conditional
是 Spring 提供的两种常用机制,它们可以根据不同的条件动态决定某些 Bean 是否加载,从而实现环境隔离、模块选择、特性开关等功能。本文将系统讲解这两个注解的作用、使用方式及它们之间的区别与协同方式。
@Profile
注解用于指定某个 Bean 或配置类仅在指定的 Profile 环境下生效。它常用于区分开发、测试和生产环境的配置。
@Configuration
@Profile("dev")
public class DevDataSourceConfig {
@Bean
public DataSource dataSource() {
return new HikariDataSource("jdbc:mysql://localhost/dev_db");
}
}
application.yml: spring.profiles.active: dev
启动参数:--spring.profiles.active=dev
SpringApplicationBuilder: .profiles("dev")
@Conditional
注解提供更通用的条件判断能力。它的参数是一个实现了 Condition
接口的类,Spring 会调用该类的 matches
方法决定是否加载对应的 Bean。
@Bean
@Conditional(WindowsCondition.class)
public ListService windowsListService() {
return new WindowsListService();
}
public class WindowsCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getEnvironment().getProperty("os.name").contains("Windows");
}
}
维度 | @Profile | @Conditional |
---|---|---|
粒度 | 环境级别配置 | 代码级别、属性级别、任意条件 |
简洁性 | 简洁易用,约定大于配置 | 灵活但需要手动实现 Condition 接口 |
适用场景 | 多环境配置隔离(dev/test/prod) | 按任意运行时条件控制 Bean 加载,如系统变量、类存在性等 |
可组合性 | 可配合 @Configuration 、@Component 使用 |
可与任意 Spring 注解组合 |
底层原理 | 本质是 @Conditional(ProfileCondition.class) |
完全自定义 Condition 实现类 |
@Configuration
@Profile("prod")
public class CacheConfig {
@Bean
@Conditional(RedisPresentCondition.class)
public CacheManager redisCacheManager() {
return new RedisCacheManager();
}
}
此配置表示仅在 prod
环境下,且类路径中存在 RedisClient
类时,才创建 redisCacheManager
Bean。
Spring Boot 提供了多个 @Conditional
的派生注解,简化了常见场景的条件配置:
作用:根据配置文件中某个属性是否存在及其值决定是否加载 Bean
@Bean
@ConditionalOnProperty(name = "feature.user.enable", havingValue = "true", matchIfMissing = false)
public UserFeatureService featureService() {
return new UserFeatureService();
}
作用:仅在指定 Bean 不存在时注册当前 Bean,用于提供默认实现。
@Bean
@ConditionalOnMissingBean(DataSource.class)
public DataSource defaultDataSource() {
return new HikariDataSource();
}
作用:当 Spring 上下文中存在某个 Bean 时,才注入当前 Bean。
@Bean
@ConditionalOnBean(RedisClient.class)
public CacheManager redisCacheManager() {
return new RedisCacheManager();
}
作用:当类路径下存在某个类时才加载 Bean,适合做组件自动装配。
@Bean
@ConditionalOnClass(name = "com.fasterxml.jackson.databind.ObjectMapper")
public JsonConverter jsonConverter() {
return new JacksonJsonConverter();
}
这些注解极大简化了自动配置的条件逻辑,是 Spring Boot 自动装配机制的核心支撑。
注解 | 作用 | 适合场景 |
---|---|---|
@Profile | 按环境(如 dev/prod)激活 Bean | 多环境隔离配置 |
@Conditional | 根据任意条件(如操作系统、类路径)激活 Bean | 灵活控制、扩展性强的模块化配置 |
在实际项目中,两者可结合使用,构建高度灵活、可配置的应用架构,是 Spring 框架解耦和模块控制的重要工具。
建议在配置类中大量使用
@Profile
做环境隔离,在具体 Bean 中使用@Conditional
做条件控制。