SpringBoot中@Conditional注解的介紹及實(shí)踐
1、簡述
在 Spring Boot 中,@Conditional 注解用于實(shí)現(xiàn) 條件化 Bean 裝配,即根據(jù)特定的條件來決定是否加載某個(gè) Bean。它是 Spring 框架中的一個(gè)擴(kuò)展機(jī)制,常用于實(shí)現(xiàn)模塊化、可配置的組件加載。
本文將詳細(xì)介紹 @Conditional 相關(guān)的注解,包括 @ConditionalOnClass、@ConditionalOnMissingBean、@ConditionalOnProperty 等,并結(jié)合實(shí)際應(yīng)用示例講解其使用方式。
2、@Conditional 注解概述
@Conditional 是 Spring 4 引入的條件裝配注解,它可以根據(jù)外部環(huán)境或配置的狀態(tài),決定是否創(chuàng)建 Bean。
其核心接口是:
public interface Condition {
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
任何實(shí)現(xiàn) Condition 接口的類,都可以用于自定義條件判斷。
@Configuration
public class MyConfig {
@Bean
@Conditional(MyCondition.class)
public MyService myService() {
return new MyService();
}
}
其中 MyCondition.class 需要實(shí)現(xiàn) Condition 接口,并提供判斷邏輯。
3、Spring Boot 內(nèi)置 @Conditional 相關(guān)注解
Spring Boot 提供了一些常見的 @Conditional 注解,簡化了條件判斷的邏輯:
| 注解 | 作用 |
|---|---|
@ConditionalOnClass | 類路徑下存在某個(gè)類時(shí),才加載該 Bean |
@ConditionalOnMissingClass | 類路徑下不存在某個(gè)類時(shí),才加載該 Bean |
@ConditionalOnBean | 當(dāng)容器中存在指定 Bean 時(shí),才加載當(dāng)前 Bean |
@ConditionalOnMissingBean | 當(dāng)容器中不存在指定 Bean 時(shí),才加載當(dāng)前 Bean |
@ConditionalOnProperty | 當(dāng)指定的配置屬性滿足條件時(shí),才加載當(dāng)前 Bean |
@ConditionalOnExpression | 當(dāng)指定的 SpEL 表達(dá)式為 true 時(shí),才加載當(dāng)前 Bean |
@ConditionalOnJava | 當(dāng) Java 版本符合要求時(shí),才加載當(dāng)前 Bean |
@ConditionalOnWebApplication | 當(dāng)應(yīng)用是 Web 應(yīng)用時(shí),才加載當(dāng)前 Bean |
@ConditionalOnNotWebApplication | 當(dāng)應(yīng)用不是 Web 應(yīng)用時(shí),才加載當(dāng)前 Bean |
3.1 @ConditionalOnClass 使用示例(類路徑檢測)
我們希望在 Spring Boot 項(xiàng)目中,當(dāng)類路徑下存在 com.example.MyLibrary 這個(gè)類時(shí),才注冊 MyService 這個(gè) Bean。
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 會(huì)被創(chuàng)建。
- 如果 com.example.MyLibrary 不存在,則 MyService 不會(huì)被加載。
3.2 @ConditionalOnMissingBean(Bean 缺失時(shí)加載)
如果用戶沒有手動(dòng)定義 MyService,則提供一個(gè)默認(rèn)實(shí)現(xiàn)。
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 容器中已經(jīng)存在 MyService,則不會(huì)創(chuàng)建新的 Bean。
- 只有當(dāng) MyService 不存在時(shí),才會(huì)注冊默認(rèn)實(shí)現(xiàn)。
3.3 @ConditionalOnProperty(基于配置項(xiàng)條件加載 Bean)
我們希望 MyService 只有在 app.feature.enabled=true 時(shí)才被創(chuàng)建。
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 會(huì)被創(chuàng)建。
- 如果 app.feature.enabled=false,或者該屬性未定義,則 MyService 不會(huì)被加載。
在 application.properties 中啟用:
app.feature.enabled=true
3.4 @ConditionalOnBean(存在特定 Bean 時(shí)才加載)
當(dāng) UserService 存在時(shí),才創(chuàng)建 OrderService。
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 也會(huì)被創(chuàng)建。
- 如果 UserService 不存在,則 OrderService 不會(huì)被加載。
3.5 @ConditionalOnExpression(基于 SpEL 表達(dá)式加載)
當(dāng) server.port 大于 8080 時(shí),才創(chuàng)建 AdvancedService。
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 時(shí),AdvancedService 會(huì)被加載。
其他情況下,不會(huì)創(chuàng)建該 Bean。
在 application.properties 中配置:
server.port=9090
3.6 結(jié)合 @ConditionalOnClass 實(shí)現(xiàn) Starter 組件的熱拔插
我們要?jiǎng)?chuàng)建一個(gè) Spring Boot Starter 組件,如果用戶的 classpath 下存在 RedisTemplate,則自動(dòng)加載 Redis 相關(guān)的 Bean。
步驟:
創(chuàng)建 Starter 組件
@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;
}
}
應(yīng)用使用 Starter
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
如果引入 Redis 依賴,RedisAutoConfiguration 會(huì)自動(dòng)生效。
如果不引入 Redis 依賴,則 RedisTemplate 不會(huì)被創(chuàng)建。
4、總結(jié)
- @Conditional 及其衍生注解使 Spring Boot 具備了自動(dòng)配置和熱拔插的能力。
- @ConditionalOnClass 可用于判斷某個(gè)類是否存在,常用于 Starter 組件的自動(dòng)裝配。
- @ConditionalOnProperty 適用于基于配置的條件加載,增強(qiáng)靈活性。
- @ConditionalOnBean 和 @ConditionalOnMissingBean 適用于組件依賴管理。
合理使用這些注解,可以構(gòu)建更加模塊化、靈活、可配置的 Spring Boot 應(yīng)用。
以上就是SpringBoot中@Conditional注解的介紹及實(shí)踐的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot @Conditional注解的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot中實(shí)現(xiàn)啟動(dòng)任務(wù)的實(shí)現(xiàn)步驟
這篇文章主要介紹了SpringBoot中實(shí)現(xiàn)啟動(dòng)任務(wù)的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
java LRU(Least Recently Used )詳解及實(shí)例代碼
這篇文章主要介紹了java LRU(Least Recently Used )詳解及實(shí)例代碼的相關(guān)資料,Java里面實(shí)現(xiàn)LRU緩存通常有兩種選擇,一種是使用LinkedHashMap,一種是自己設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu),使用鏈表+HashMap,需要的朋友可以參考下2016-11-11
spring-boot https證書雙向認(rèn)證配置的實(shí)現(xiàn)
本文詳細(xì)介紹SpringBoot項(xiàng)目中配置自簽名CA證書、簽發(fā)服務(wù)端和客戶端證書,生成PKCS12格式的證書,及設(shè)置SSL/TLS配置,實(shí)現(xiàn)雙向認(rèn)證,具有一定的參考價(jià)值,感興趣的可以了解一下2025-08-08
Java實(shí)現(xiàn)stream的三個(gè)常用方式(toMap,groupingBy,findFirst)
本文主要介紹了Java實(shí)現(xiàn)stream的三個(gè)常用方式,主要包括toMap,groupingBy,findFirst,具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10
Java多線程Future松獲取異步任務(wù)結(jié)果輕松實(shí)現(xiàn)
這篇文章主要為大家介紹了Java多線程Future松獲取異步任務(wù)結(jié)果輕松實(shí)現(xiàn)方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04
詳解Spring關(guān)于@Resource注入為null解決辦法
這篇文章主要介紹了詳解Spring關(guān)于@Resource注入為null解決辦法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
Java多線程事務(wù)回滾@Transactional失效處理方案
這篇文章主要介紹了Java多線程事務(wù)回滾@Transactional失效處理方案,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下2022-08-08

