JAVA:Spring Boot @Conditional 注解詳解及實踐

1、簡述

在 Spring Boot 中,@Conditional 注解用于實現 條件化 Bean 裝配,即根據特定的條件來決定是否加載某個 Bean。它是 Spring 框架中的一個擴展機制,常用于實現模塊化、可配置的組件加載。

本文將詳細介紹 @Conditional 相關的注解,包括 @ConditionalOnClass@ConditionalOnMissingBean@ConditionalOnProperty 等,并結合實際應用示例講解其使用方式。

在這里插入圖片描述


2、@Conditional 注解概述

@Conditional 是 Spring 4 引入的條件裝配注解,它可以根據外部環境或配置的狀態,決定是否創建 Bean。

其核心接口是:

public interface Condition {boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}

任何實現 Condition 接口的類,都可以用于自定義條件判斷

@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。

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,則提供一個默認實現。

import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MyAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic MyService myService() {return new MyService("Default Implementation");}
}

解釋:

  • 如果 Spring 容器中已經存在 MyService,則不會創建新的 Bean。
  • 只有當 MyService 不存在時,才會注冊默認實現。

3.3 @ConditionalOnProperty(基于配置項條件加載 Bean)

我們希望 MyService 只有在 app.feature.enabled=true 時才被創建。

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 中啟用:

app.feature.enabled=true

3.4 @ConditionalOnBean(存在特定 Bean 時才加載)

UserService 存在時,才創建 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 也會被創建。
  • 如果 UserService 不存在,則 OrderService 不會被加載

3.5 @ConditionalOnExpression(基于 SpEL 表達式加載)

server.port 大于 8080 時,才創建 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 時,AdvancedService 會被加載。
  • 其他情況下,不會創建該 Bean。

application.properties 中配置:

server.port=9090

3.6 結合 @ConditionalOnClass 實現 Starter 組件的熱拔插

我們要創建一個 Spring Boot Starter 組件,如果用戶的 classpath 下存在 RedisTemplate,則自動加載 Redis 相關的 Bean。

步驟:
創建 Starter 組件

@Configuration
@ConditionalOnClass(RedisTemplate.class)
public class RedisAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(factory);return template;}
}

應用使用 Starter

<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 應用。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/899087.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/899087.shtml
英文地址,請注明出處:http://en.pswp.cn/news/899087.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用python爬取網絡資源

整體思路 網絡資源爬取通常分為以下幾個步驟&#xff1a; 發送 HTTP 請求&#xff1a;使用requests庫向目標網站發送請求&#xff0c;獲取網頁的 HTML 內容。解析 HTML 內容&#xff1a;使用BeautifulSoup庫解析 HTML 內容&#xff0c;從中提取所需的數據。處理數據&#xff…

PostgreSQL 數據庫源碼編譯安裝全流程詳解 Linux 8

PostgreSQL 數據庫源碼編譯安裝全流程詳解 Linux 8 1. 基礎環境配置1.1 修改主機名1.2 配置操作系統yum源1.3 安裝操作系統依賴包1.4 禁用SELINUX配置1.5 關閉操作系統防火墻1.6 創建用戶和組1.7 建立安裝目錄1.8 編輯環境變量 2. 源碼方式安裝&#xff08;PG 16&#xff09;2.…

(基本常識)C++中const與引用——面試常問

作者&#xff1a;求一個demo 版權聲明&#xff1a;著作權歸作者所有&#xff0c;商業轉載請聯系作者獲得授權&#xff0c;非商業轉載請注明出處 內容通俗易懂&#xff0c;沒有廢話&#xff0c;文章最后是面試常問內容&#xff08;建議通過標題目錄學習&#xff09; 廢話不多…

Java并發編程 什么是分布式鎖 跟其他的鎖有什么區別 底層原理 實戰講解

目錄 一、分布式鎖的定義與核心作用 二、分布式鎖與普通鎖的核心區別 三、分布式鎖的底層原理與實現方式 1. 核心實現原理 2. 主流實現方案對比 3. 關鍵技術細節 四、典型問題與解決方案 五、總結 六、具體代碼實現 一、分布式鎖的定義與核心作用 分布式鎖是一種在分布…

案例:使用網絡命名空間模擬多主機并通過網橋訪問外部網絡

案例目標 隔離性&#xff1a;在同一臺物理機上創建兩個獨立的網絡命名空間&#xff08;模擬兩臺主機&#xff09;&#xff0c;確保其網絡配置完全隔離。內部通信&#xff1a;允許兩個命名空間通過虛擬設備直接通信。外部訪問&#xff1a;通過宿主機的網橋和 NAT 規則&#xff…

AF3 Rotation 類解讀

Rotation 類(rigid_utils 模塊)是 AlphaFold3 中用于 3D旋轉 的核心組件,支持兩種旋轉表示: 1?? 旋轉矩陣 (3x3) 2?? 四元數 (quaternion, 4元向量) ?? 設計目標: 允許靈活選擇 旋轉矩陣 或 四元數 封裝了常用的 旋轉操作(組合、逆旋轉、應用到點上等) 像 torch.…

DeepSeek面試——模型架構和主要創新點

本文將介紹DeepSeek的模型架構多頭潛在注意力&#xff08;MLA&#xff09;技術&#xff0c;混合專家&#xff08;MoE&#xff09;架構&#xff0c; 無輔助損失負載均衡技術&#xff0c;多Token 預測&#xff08;MTP&#xff09;策略。 一、模型架構 DeepSeek-R1的基本架構沿用…

【web3】

檢測錢包是否安裝 方法一 // npm install metamask/detect-provider import detectEthereumProvider from metamask/detect-provider// 檢測錢包是否安裝 const isProvider await detectEthereumProvider() if(!isProvider) {proxy.$modal.msgError("請安裝錢包")…

husky的簡介以及如果想要放飛自我的解決方案

husky 是一個 Git Hooks 管理工具&#xff0c;它的主要作用是 在 Git 提交&#xff08;commit&#xff09;、推送&#xff08;push&#xff09;等操作時執行自定義腳本&#xff0c;比如代碼檢查&#xff08;Lint&#xff09;、單元測試&#xff08;Test&#xff09;、格式化代碼…

JVM之類的加載過程

加載 這一階段是將類的字節碼從外部存儲&#xff08;如磁盤&#xff09;加載到JVM的內存中。加載時&#xff0c;JVM會根據類的全限定名&#xff08;包括包名和類名&#xff09;查找相應的字節碼文件&#xff08;.class文件&#xff09;&#xff0c;并將其讀入內存。 鏈接 鏈接…

Java Collection API增強功能系列之六 改進的 ConcurrentHashMap:歸約、搜索、計數與 Set 視圖詳解

Java 8 改進的 ConcurrentHashMap&#xff1a;歸約、搜索、計數與 Set 視圖詳解 Java 8 對 ConcurrentHashMap 進行了重大優化&#xff0c;不僅提升了并發性能&#xff0c;還引入了許多函數式編程方法&#xff0c;使其在處理高并發場景時更加高效和靈活。本文將深入解析 Concu…

AI生成移動端貪吃蛇游戲頁面,手機瀏覽器打開即可玩

貪吃蛇游戲可計分&#xff0c;可穿墻&#xff0c;AI生成適配手機瀏覽器的游戲&#xff0c;代碼如下&#xff1a; <!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"UTF-8"> <meta name"viewport" …

【動手學深度學習】#4 深度學習計算

主要參考學習資料&#xff1a; 《動手學深度學習》阿斯頓張 等 著 【動手學深度學習 PyTorch版】嗶哩嗶哩跟李牧學AI 概述 為了實現更復雜的網絡&#xff0c;我們需要研究比層更高一級的單元塊&#xff0c;在編程中由類表示。通過自定義層和塊&#xff0c;我們能更靈活地搭建網…

如何在 Windows 上安裝并使用 Postman?

Postman 是一個功能強大的API測試工具&#xff0c;它可以幫助程序員更輕松地測試和調試 API。在本文中&#xff0c;我們將討論如何在 Windows 上安裝和使用 Postman。 Windows 如何安裝和使用 Postman 教程&#xff1f;

php寫入\查詢influxdb數據

namespace app\index\controller;use InfluxDB2\Client; use InfluxDB2\Model\WritePrecision; use InfluxDB2\Point;class Demo {/*** 顯示資源列表** return \think\Response*/public function index(){$token 你的TOKEN;$org zzlichi;$bucket initdb;$client new Client…

26考研——圖_圖的基本概念(6)

408答疑 文章目錄 一、圖的基本概念圖的定義非空性非線性結構 頂點和邊的表示頂點邊 有向圖 & 無向圖有向圖有向圖 G 1 G_1 G1? 的表示 無向圖無向圖 G 2 G_2 G2? 的表示 簡單圖 & 多重圖簡單圖多重圖 頂點的度、入度和出度頂點的度有向圖的度 路徑、路徑長度和回路…

面向對象軟件工程實踐軟件案例

智力運動-數字化思維訓練課程介紹 數字化思維訓練是科技賦能素質教育創新實踐項目&#xff0c;通過數字化信息化手段&#xff0c;深度融合優質原創智力運動教育課程資源&#xff0c;服務幼兒園與小學&#xff0c;提供信息時代校園素質教育教學解決方案。在《面向對象軟件工程》…

Linux學習筆記(應用篇一)

基于I.MX6ULL.MINI開發板 標準I/O庫鏈接目錄刪除文件正則表達式系統標識時間堆內存信號標準信號 進程進程組進程間通信線程互斥鎖線程安全 本文章是入門篇的概念&#xff0c;有點零散&#xff0c;后續需要補充復習 **inode&#xff08;索引節點&#xff09;**是 Linux 和 Unix …

Modbus RTU ---> Modbus TCP透傳技術實現(Modbus透傳、RS485透傳、RTU透傳)分站代碼實現、協議轉換器

文章目錄 Modbus RTU到Modbus TCP透傳技術實現1. 透傳技術概述1.1 透傳基本原理- 協議幀格式轉換- 地址映射與管理- 通信時序適配- 錯誤檢測與處理 2. 透傳網關硬件架構2.1 典型硬件結構- 微控制器/處理器(ARM、STM32等)- RS-485/RS-232收發器- 以太網控制器(如W5500)- 電源管理…

MySQL數據庫中常用的命令

登錄&#xff1a; mysql -u username -h ip地址 -P 端口 -p 密碼 mysql -u username -S /path/mysql.sock -P -p 用戶管理&#xff1a; select user,host from mysql.user;//查看數據庫中所用用戶信息 create user username%;//創建用戶 create user username% identifie…