Spring Boot 中的 @ConditionalOnBean 注解場(chǎng)景分析
1. 前言
在 Spring Boot 中,條件注解(Conditional 注解) 是一種強(qiáng)大的功能,允許我們根據(jù)某些條件動(dòng)態(tài)地注冊(cè)或跳過(guò)特定的 Bean。其中,@ConditionalOnBean
是最常用的條件注解之一,它的作用是:當(dāng) Spring 容器中存在指定的 Bean 時(shí),當(dāng)前 Bean 才會(huì)被注冊(cè)。
本篇文章將詳細(xì)介紹 @ConditionalOnBean
的使用場(chǎng)景、原理,并提供多個(gè)示例幫助理解。
2. @ConditionalOnBean 作用與基本用法
2.1 @ConditionalOnBean 的作用
@ConditionalOnBean
主要用于以下場(chǎng)景:
- 按需加載 Bean:只有在某個(gè) Bean 存在時(shí),另一個(gè) Bean 才會(huì)被創(chuàng)建。
- 模塊化設(shè)計(jì):某些功能模塊需要依賴特定 Bean 才能啟用,例如 僅當(dāng)某個(gè)組件存在時(shí),自動(dòng)配置才會(huì)生效。
- 避免 Bean 沖突:如果某個(gè) Bean 依賴其他 Bean,則可使用
@ConditionalOnBean
確保它不會(huì)因缺少依賴而加載失敗。
2.2 基本用法
示例:當(dāng) DataSource
Bean 存在時(shí),才創(chuàng)建 MyService
Bean
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; @Configuration public class MyConfig { @Bean public DataSource dataSource() { // 這里模擬 DataSource 實(shí)例,實(shí)際可用 HikariDataSource、Druid 等 return new FakeDataSource(); } @Bean @ConditionalOnBean(DataSource.class) // 僅當(dāng) DataSource 存在時(shí),才創(chuàng)建 MyService public MyService myService() { return new MyService(); } } class MyService { public MyService() { System.out.println("MyService 被創(chuàng)建"); } } class FakeDataSource implements DataSource { // 這里可以模擬 DataSource 方法 }
執(zhí)行結(jié)果:
MyService 被創(chuàng)建
如果 dataSource()
方法被注釋掉,則 MyService
不會(huì)被創(chuàng)建。
3. @ConditionalOnBean 詳解
@ConditionalOnBean
提供了多個(gè)屬性,可以更加靈活地控制 Bean 的創(chuàng)建。
3.1 value 和 type 屬性(指定 Bean 類型)
用于指定某種類型的 Bean 存在時(shí),當(dāng)前 Bean 才會(huì)被注冊(cè)。
@Bean @ConditionalOnBean(value = DataSource.class) // 僅當(dāng) DataSource 存在時(shí)生效 public MyRepository myRepository() { return new MyRepository(); }
等效于:
@Bean @ConditionalOnBean(type = "javax.sql.DataSource") // 使用全限定類名 public MyRepository myRepository() { return new MyRepository(); }
區(qū)別:
value
:直接使用 Class 類型,編譯時(shí)檢查更安全。type
:使用字符串,可用于避免某些類找不到(如可選依賴)。
3.2 name 屬性(指定 Bean 名稱)
用于 指定某個(gè) Bean 名稱是否存在 來(lái)決定當(dāng)前 Bean 是否加載。
@Bean @ConditionalOnBean(name = "customBean") // 僅當(dāng)名為 customBean 的 Bean 存在時(shí)注冊(cè) public MyComponent myComponent() { return new MyComponent(); }
3.3 annotation 屬性(指定 Bean 需要標(biāo)注的注解)
可以指定某些 Bean 是否包含特定注解,如果包含,則當(dāng)前 Bean 才會(huì)被注冊(cè)。
@Bean @ConditionalOnBean(annotation = Repository.class) // 僅當(dāng)存在 @Repository 注解的 Bean 時(shí)生效 public MyService myService() { return new MyService(); }
3.4 search 屬性(搜索范圍)
默認(rèn)情況下,@ConditionalOnBean
只會(huì)在 當(dāng)前應(yīng)用上下文 中查找 Bean,而不會(huì)查找 父上下文(即 Spring Boot 的 ApplicationContext
層級(jí))。
search
選項(xiàng)可以指定搜索范圍:
ALL
:在所有父子ApplicationContext
中搜索。CURRENT
(默認(rèn)):僅搜索當(dāng)前ApplicationContext
。
@Bean @ConditionalOnBean(value = DataSource.class, search = SearchStrategy.ALL) // 在所有上下文中搜索 public MyService myService() { return new MyService(); }
4.@ConditionalOnBean 使用場(chǎng)景
場(chǎng)景 1:按需加載數(shù)據(jù)庫(kù)相關(guān) Bean
如果應(yīng)用程序中 使用了數(shù)據(jù)庫(kù),則提供一個(gè) DatabaseService
,否則不創(chuàng)建:
@Bean @ConditionalOnBean(DataSource.class) public DatabaseService databaseService() { return new DatabaseService(); }
場(chǎng)景 2:?jiǎn)⒂媚承┳詣?dòng)配置
Spring Boot 的 spring-boot-autoconfigure
模塊大量使用 @ConditionalOnBean
來(lái)控制自動(dòng)配置。例如:
只有當(dāng) DispatcherServlet
存在時(shí),Spring MVC 相關(guān)的自動(dòng)配置才會(huì)生效。
@Configuration @ConditionalOnBean(DispatcherServlet.class) public class MvcAutoConfiguration { // 僅當(dāng) DispatcherServlet 存在時(shí),Spring MVC 配置生效 }
場(chǎng)景 3:可選依賴的組件
有時(shí),某些功能是可選的,比如當(dāng) Redis 組件存在時(shí),才創(chuàng)建緩存管理器:
@Bean @ConditionalOnBean(name = "redisTemplate") // 只有當(dāng) redisTemplate 存在時(shí)才加載 public CacheManager cacheManager() { return new RedisCacheManager(); }
5. @ConditionalOnBean vs @ConditionalOnMissingBean
注解 | 作用 |
---|---|
@ConditionalOnBean | 當(dāng)指定 Bean 存在時(shí),才注冊(cè)當(dāng)前 Bean |
@ConditionalOnMissingBean | 當(dāng)指定 Bean 不存在時(shí),才注冊(cè)當(dāng)前 Bean |
示例:
@Bean @ConditionalOnMissingBean(DataSource.class) // 僅當(dāng) DataSource 不存在時(shí)才創(chuàng)建 public DataSource defaultDataSource() { return new DefaultDataSource(); }
6. 結(jié)論
在 Spring Boot 中,@ConditionalOnBean
可以幫助我們根據(jù) 是否存在特定 Bean 來(lái) 動(dòng)態(tài)注冊(cè) Bean,廣泛用于 按需加載、自動(dòng)配置 等場(chǎng)景。
總結(jié):
? 指定 Bean 類型:@ConditionalOnBean(DataSource.class)
? 指定 Bean 名稱:@ConditionalOnBean(name = "customBean")
? 指定 Bean 注解:@ConditionalOnBean(annotation = Repository.class)
? 搜索范圍:@ConditionalOnBean(search = SearchStrategy.ALL)
你在項(xiàng)目中用過(guò) @ConditionalOnBean
嗎?歡迎留言分享你的經(jīng)驗(yàn)!??
到此這篇關(guān)于Spring Boot 中的 @ConditionalOnBean 注解詳解的文章就介紹到這了,更多相關(guān)Spring Boot @ConditionalOnBean 注解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java使用EasyExcel實(shí)現(xiàn)高效的Excel讀寫操作
在日常開發(fā)中,Excel 文件的讀寫操作是一個(gè)常見的需求,EasyExcel 是阿里巴巴開源的一個(gè)高性能、易用的 Excel 讀寫庫(kù),可以大幅提高處理 Excel 文件的效率,本篇博客將從 EasyExcel 的基本概念、優(yōu)勢(shì)、安裝、讀寫操作以及高級(jí)用法展開,需要的朋友可以參考下2024-12-12Sentinel流控規(guī)則實(shí)現(xiàn)限流保護(hù)詳解
這篇文章主要介紹了Sentinel流控規(guī)則實(shí)現(xiàn)限流保護(hù),Sentinel是一個(gè)分布式系統(tǒng)的流量控制組件,它可以實(shí)現(xiàn)限流,流控,降級(jí)等功能,提高系統(tǒng)的穩(wěn)定性和可靠性,感興趣想要詳細(xì)了解可以參考下文2023-05-05小白必看toString(),String.valueOf,(String)強(qiáng)轉(zhuǎn)
在Java中,往往需要把一個(gè)類型的變量轉(zhuǎn)換成String 類型,本文主要介紹了toString(),String.valueOf,(String)強(qiáng)轉(zhuǎn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06如何解決java中遇到的for input string: "" 報(bào)錯(cuò)問(wèn)題
在本篇文章里小編給大家整理的是一篇關(guān)于如何解決java中遇到的(for input string: "")報(bào)錯(cuò)內(nèi)容,需要的朋友們可以學(xué)習(xí)下。2020-02-02詳解Java中CountDownLatch異步轉(zhuǎn)同步工具類
今天給大家?guī)?lái)的是關(guān)于Java的相關(guān)知識(shí),文章圍繞著CountDownLatch異步轉(zhuǎn)同步工具類展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06Java+Windows+ffmpeg實(shí)現(xiàn)視頻轉(zhuǎn)換功能
這篇文章主要為大家詳細(xì)介紹了Java+Windows+ffmpeg實(shí)現(xiàn)視頻轉(zhuǎn)換功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12IntelliJ?IDEA教程之clean或者install?Maven項(xiàng)目的操作方法
這篇文章主要介紹了IntelliJ?IDEA教程之clean或者install?Maven項(xiàng)目的操作方法,本文分步驟給大家介紹兩種方式講解如何調(diào)試出窗口,需要的朋友可以參考下2023-04-04