1、简述
在 Spring Boot 中,@Conditional 注解用于实现 条件化 Bean 装配 ,即根据特定的条件来决定是否加载某个 Bean。它是 Spring 框架中的一个扩展机制,常用于实现模块化、可配置的组件加载。
本文将详细介绍 @Conditional 相关的注解,包括 @ConditionalOnClass 、@ConditionalOnMissingBean 、@ConditionalOnProperty 等,并结合实际应用示例讲解其使用方式。

2、@Conditional 注解概述
@Conditional 是 Spring 4 引入的条件装配注解,它可以根据外部环境或配置的状态,决定是否创建 Bean。
其核心接口是:
java
public interface Condition {
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
任何实现 Condition
接口的类,都可以用于自定义条件判断。
java
@Configuration
public class MyConfig {
@Bean
@Conditional(MyCondition.class)
public MyService myService() {
return new MyService();
}
}
其中 MyCondition.class
需要实现 Condition
接口,并提供判断逻辑。
3、Spring Boot 内置 @Conditional 相关注解
Spring Boot 提供了一些常见的 @Conditional
注解,简化了条件判断的逻辑:
注解 | 作用 |
---|---|
@ConditionalOnClass |
类路径下存在某个类时,才加载该 Bean |
@ConditionalOnMissingClass |
类路径下不存在某个类时,才加载该 Bean |
@ConditionalOnBean |
当容器中存在指定 Bean 时,才加载当前 Bean |
@ConditionalOnMissingBean |
当容器中不存在指定 Bean 时,才加载当前 Bean |
@ConditionalOnProperty |
当指定的配置属性满足条件时,才加载当前 Bean |
@ConditionalOnExpression |
当指定的 SpEL 表达式为 true 时,才加载当前 Bean |
@ConditionalOnJava |
当 Java 版本符合要求时,才加载当前 Bean |
@ConditionalOnWebApplication |
当应用是 Web 应用时,才加载当前 Bean |
@ConditionalOnNotWebApplication |
当应用不是 Web 应用时,才加载当前 Bean |
3.1 @ConditionalOnClass 使用示例(类路径检测)
我们希望在 Spring Boot 项目中 ,当类路径下存在 com.example.MyLibrary
这个类时,才注册 MyService
这个 Bean。
java
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyAutoConfiguration {
@Bean
@ConditionalOnClass(name = "com.example.MyLibrary")
public MyService myService() {
return new MyService();
}
}
解释:
- 如果
com.example.MyLibrary
存在 ,则MyService
会被创建。 - 如果
com.example.MyLibrary
不存在 ,则MyService
不会被加载。
3.2 @ConditionalOnMissingBean(Bean 缺失时加载)
如果用户没有手动定义 MyService
,则提供一个默认实现。
java
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MyService myService() {
return new MyService("Default Implementation");
}
}
解释:
- 如果 Spring 容器中已经存在
MyService
,则不会创建新的 Bean。 - 只有当
MyService
不存在时,才会注册默认实现。
3.3 @ConditionalOnProperty(基于配置项条件加载 Bean)
我们希望 MyService
只有在 app.feature.enabled=true
时才被创建。
java
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyAutoConfiguration {
@Bean
@ConditionalOnProperty(name = "app.feature.enabled", havingValue = "true", matchIfMissing = false)
public MyService myService() {
return new MyService();
}
}
解释:
- 如果
application.properties
中包含app.feature.enabled=true
,则MyService
会被创建。 - 如果
app.feature.enabled=false
,或者该属性未定义 ,则MyService
不会被加载。
在 application.properties
中启用:
properties
app.feature.enabled=true
3.4 @ConditionalOnBean(存在特定 Bean 时才加载)
当 UserService
存在时,才创建 OrderService
。
java
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class OrderServiceConfiguration {
@Bean
@ConditionalOnBean(UserService.class)
public OrderService orderService() {
return new OrderService();
}
}
解释:
- 如果
UserService
存在,则OrderService
也会被创建。 - 如果
UserService
不存在 ,则OrderService
不会被加载。
3.5 @ConditionalOnExpression(基于 SpEL 表达式加载)
当 server.port
大于 8080 时,才创建 AdvancedService
。
java
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AdvancedConfig {
@Bean
@ConditionalOnExpression("#{T(java.lang.Integer).parseInt('${server.port:8080}') > 8080}")
public AdvancedService advancedService() {
return new AdvancedService();
}
}
解释:
server.port
> 8080 时,AdvancedService
会被加载。- 其他情况下,不会创建该 Bean。
在 application.properties
中配置:
properties
server.port=9090
3.6 结合 @ConditionalOnClass 实现 Starter 组件的热拔插
我们要创建一个 Spring Boot Starter 组件 ,如果用户的 classpath
下存在 RedisTemplate
,则自动加载 Redis 相关的 Bean。
步骤:
创建 Starter 组件
java
@Configuration
@ConditionalOnClass(RedisTemplate.class)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
return template;
}
}
应用使用 Starter
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- 如果引入 Redis 依赖 ,
RedisAutoConfiguration
会自动生效。 - 如果不引入 Redis 依赖 ,则
RedisTemplate
不会被创建。
4、总结
@Conditional
及其衍生注解使 Spring Boot 具备了自动配置 和热拔插的能力。@ConditionalOnClass
可用于判断某个类是否存在,常用于 Starter 组件的自动装配。@ConditionalOnProperty
适用于基于配置的条件加载,增强灵活性。@ConditionalOnBean
和@ConditionalOnMissingBean
适用于组件依赖管理。
合理使用这些注解,可以构建更加模块化、灵活、可配置的 Spring Boot 应用。