SpringBoot中的@Conditional?注解的使用
概述
Spring boot 中的 @Conditional 注解是一個(gè)不太常用到的注解,但確實(shí)非常的有用,我們知道 Spring Boot 是根據(jù)配置文件中的內(nèi)容,決定是否創(chuàng)建 bean,以及如何創(chuàng)建 bean 到 Spring 容器中,而 Spring boot 自動(dòng)化配置的核心控制,就是 @Conditional 注解。
@Conditional 注解是 Spring 4.0 之后出的一個(gè)注解,與其搭配的一個(gè)接口是 Condition,@Conditional 注解會(huì)根據(jù)具體的條件決定是否創(chuàng)建 bean 到容器中,接下來(lái)看看 @Conditional 注解的簡(jiǎn)單使用。
1. @Conditional 和 Condition 接口搭配使用
這里需要實(shí)現(xiàn)的功能是,我們根據(jù)配置文件中的具體內(nèi)容,來(lái)決定是否創(chuàng)建 bean,首先我們?cè)?application.yml 中加上一個(gè)自定義配置:
這里我們決定,這個(gè)配置中包含了 product 這個(gè)字符串的時(shí)候,才創(chuàng)建 bean。Product 是我自己隨便創(chuàng)建的一個(gè)實(shí)體類(lèi),你可以自行創(chuàng)建。
新建一個(gè)類(lèi) ProductCondition
,內(nèi)容如下:
public class ProductCondition implements Condition { @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { //從配置文件中獲取屬性 String property = conditionContext.getEnvironment().getProperty("create.bean"); if (property != null){ return property.contains("product"); } else { return false; } } }
這個(gè)類(lèi)實(shí)現(xiàn)了 Condition 接口,這個(gè)接口只有一個(gè)方法,我們從配置文件中獲取剛才創(chuàng)建的自定義配置,如果配置中包含了 product 這個(gè)字符串,就會(huì)返回 true。
接下來(lái)創(chuàng)建一個(gè)配置類(lèi) ProductConfig,內(nèi)容如下:
@Configuration public class ProductConfig { @Conditional(ProductCondition.class) @Bean(name = "product") public Product createProd(){ return Product.builder().id(12312).categoryId(12). productName("Mac Book Pro").productImg("prod.png") .productPrice(18000).build(); } }
我們?cè)趧?chuàng)建的 bean 方法前面加上了 @Conditional 注解,判斷的標(biāo)準(zhǔn)是剛才的 ProductCondition,如果是 true,則創(chuàng)建 bean,否則不創(chuàng)建。我們寫(xiě)一個(gè)測(cè)試類(lèi),來(lái)測(cè)試一下 bean 是否被創(chuàng)建了。測(cè)試代碼如下:
@Slf4j @SpringBootTest @RunWith(SpringRunner.class) public class ProductConfigTest { @Test public void createProd() { try { Product product = SpringContextUtil.getBean("product", Product.class); if (product != null){ System.out.println("創(chuàng)建了 bean : " + product.toString()); } } catch (Exception e){ log.info("發(fā)生異常,{}", e.getMessage()); System.out.println("沒(méi)有創(chuàng)建 bean"); } } }
運(yùn)行測(cè)試代碼,發(fā)現(xiàn) bean 已經(jīng)創(chuàng)建了:
如果把 application.yml 中的配置改一下,不包含 product 這個(gè)字符串,那么返回的是 false,bean 則不會(huì)被創(chuàng)建,你可以試一下。
2. @ConditionalOnClass 的使用
這個(gè)注解的屬性可以跟上一個(gè)類(lèi)的完整路徑或者是類(lèi)的 Class 對(duì)象,如果類(lèi)存在,則會(huì)創(chuàng)建 bean,例如下面的例子:
@Configuration public class ProductConfig { @ConditionalOnClass(name = "com.roseduan.demo.entity.Product") @Bean(name = "product") public Product createProd(){ return Product.builder().id(12312).categoryId(12). productName("Mac Book Pro").productImg("prod.png") .productPrice(18000).build(); } }
這個(gè)路徑下面的實(shí)體類(lèi) Product 是存在的,所以會(huì)創(chuàng)建 bean,如果是一個(gè)不存在的類(lèi),則不會(huì)創(chuàng)建。
3. @ConditionalOnProperty 的使用
這個(gè)注解可以直接從配置文件中獲取屬性,然后做為是否創(chuàng)建 bean 的依據(jù)。例如我們?cè)?application.yml 中添加一個(gè)自定義配置:
ProductConfig 類(lèi)的內(nèi)容是這樣的:
@Configuration public class ProductConfig { @ConditionalOnProperty(value = "create.product.bean") @Bean(name = "product") public Product createProd(){ return Product.builder().id(12312).categoryId(12). productName("Mac Book Pro").productImg("prod.png") .productPrice(18000).build(); } }
這里使用了 @ConditionalOnProperty 注解,從文件中讀取配置,因?yàn)槲覀冊(cè)O(shè)置的是 true,所以這個(gè) bean 會(huì)被創(chuàng)建,如果設(shè)置成 false,則 bean 不會(huì)被創(chuàng)建,你可以自己試一下。根據(jù)這個(gè)特性,我們可以給一些特定的配置加上一個(gè)開(kāi)關(guān),非常方便控制。
4.@Conditional 的實(shí)現(xiàn)子注解
springboot 提供了大量的 @Conditional 子注解供我們使用,我們只需知道有哪些常用的子注解供我們使用即可。
springboot 提供的 @Conditional 子注解有:
@ConditionalOnBean @ConditionalOnClass @ConditionalOnCloudPlatform @ConditionalOnExpression @ConditionalOnJava @ConditionalOnJndi @ConditionalOnMissingBean @ConditionalOnMissingClass @ConditionalOnNotWebApplication @ConditionalOnProperty @ConditionalOnResource @ConditionalOnSingleCandidate @ConditionalOnWarDeployment @ConditionalOnWebApplication 這些子注解是如何實(shí)現(xiàn)的呢?我們以 @ConditionalOnBean 注解為例看下源碼: @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Conditional({OnBeanCondition.class}) public @interface ConditionalOnBean { Class<?>[] value() default {}; String[] type() default {}; Class<? extends Annotation>[] annotation() default {}; String[] name() default {}; SearchStrategy search() default SearchStrategy.ALL; Class<?>[] parameterizedContainer() default {}; }
可以看到 OnBeanCondition 是 Condition 接口的具體實(shí)現(xiàn)類(lèi)。
我們挑選一些日常常用的子注解做具體的說(shuō)明。
這里我只是列舉了幾個(gè)常用的注解,你可以查看官方文檔,里面有更詳細(xì)的說(shuō)明:
參考文檔:官網(wǎng)文檔
到此這篇關(guān)于SpringBoot中的@Conditional 注解的使用的文章就介紹到這了,更多相關(guān)SpringBoot @Conditional注解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java 添加、修改、讀取、復(fù)制、刪除Excel批注的實(shí)現(xiàn)
這篇文章主要介紹了Java 添加、修改、讀取、復(fù)制、刪除Excel批注的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02SpringBoot下無(wú)節(jié)制和數(shù)據(jù)庫(kù)建立連接的問(wèn)題及解決方法
本文介紹了無(wú)節(jié)制建立MySQL連接的危害,包括數(shù)據(jù)庫(kù)服務(wù)端資源耗盡、應(yīng)用端性能劣化和監(jiān)控與運(yùn)維困境,提出了系統(tǒng)性解決方案,包括連接池標(biāo)準(zhǔn)化配置、代碼規(guī)范與防御式編程、全鏈路監(jiān)控體系和架構(gòu)級(jí)優(yōu)化,感興趣的朋友一起看看吧2025-03-03Java中實(shí)現(xiàn)高清圖片壓縮的兩種方案(最新推薦)
文章首先介紹了Java中進(jìn)行高清圖片壓縮的基本方法,包括使用Java標(biāo)準(zhǔn)庫(kù)ImageIO和第三方庫(kù)ApacheCommonsCompress,通過(guò)示例代碼展示了如何調(diào)整圖像質(zhì)量和使用第三方工具來(lái)壓縮圖片文件,感興趣的朋友跟隨小編一起看看吧2025-01-01springboot多環(huán)境進(jìn)行動(dòng)態(tài)配置的方法
這篇文章主要介紹了springboot多環(huán)境下如何進(jìn)行動(dòng)態(tài)配置,本文主要分享了如何在springboot的項(xiàng)目中使用多環(huán)境配置,重點(diǎn)是”spring.profiles.active“屬性,需要的朋友可以參考下2022-06-06JavaWeb利用struts實(shí)現(xiàn)文件下載時(shí)改變文件名稱(chēng)
這篇文章主要為大家詳細(xì)介紹了JavaWeb利用struts實(shí)現(xiàn)文件下載時(shí)改變文件名稱(chēng)的相關(guān)資料,需要的朋友可以參考下2016-06-06java編程中實(shí)現(xiàn)調(diào)用js方法分析
這篇文章主要介紹了java編程中實(shí)現(xiàn)調(diào)用js方法,結(jié)合具體實(shí)例形式較為詳細(xì)的分析了java編程中調(diào)用js方法的常用操作技巧與注意事項(xiàng),需要的朋友可以參考下2017-09-09