Spring使用@Conditional進(jìn)行條件裝配的實(shí)現(xiàn)
在spring中有些bean需要滿足某些環(huán)境條件才創(chuàng)建某個(gè)bean,這個(gè)時(shí)候可以在bean定義上使用@Conditional注解來修飾。@Conditional需要指定一個(gè)條件類,這個(gè)類不需實(shí)現(xiàn)Condition接口并且實(shí)現(xiàn)其matches方法。只有當(dāng)matches方法返回true時(shí)才創(chuàng)建當(dāng)前bean。
例如下面定義一個(gè)bean只有當(dāng)當(dāng)前jdk版本大于等于8時(shí)才創(chuàng)建該bean。
bean定義這里寫的很簡(jiǎn)單,
@Service @Conditional(Java8Condition.class) public class ConditionService { }
看Java8Condition條件類
public class Java8Condition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { return JavaVersion.getJavaVersion().isEqualOrNewerThan(JavaVersion.EIGHT); } }
這里判斷當(dāng)前java的版本,如果大于等于8則返回true,ConditionService會(huì)被創(chuàng)建成bean,否則不會(huì)創(chuàng)建該bean。
Condition的matches方法有兩個(gè)入?yún)ⅲ琧ontext和metadata。從context可以獲取beanFactory和environment信息,從metadata可以獲取當(dāng)前bean上所有注解配置信息。通過這兩個(gè)參數(shù)可以獲取到很多信息了,這里就可以根據(jù)上下文來進(jìn)行判斷。不如beanFacotry是否有某個(gè)bean,當(dāng)前環(huán)境的profile信息,某個(gè)屬性的配置信息等等。
看到這里你是否想到了些什么,沒錯(cuò)就是springboot的自動(dòng)條件裝配。springboot對(duì)@Conditional進(jìn)行了擴(kuò)展,在org.springframework.boot.autoconfigure.condition包下有很多封裝好的條件注解。如
ConditionalOnBean:某個(gè)bean存在時(shí)
ConditionalOnClass: 某個(gè)class存在時(shí)
ConditionalOnExpression: SpEL表達(dá)式成立時(shí)
ConditionalOnJava: java環(huán)境版本
ConditionalOnProperty: 某個(gè)property值是多少時(shí)
ConditionalOnMissingBean: 某個(gè)bean不存在時(shí)
等等還有很多。這就明白為什么有些bean我們沒有顯示聲明可以直接拿來注入使用了吧。
condition的擴(kuò)展
雖然springboot也封裝了很多場(chǎng)景的condition注解,但是難免有時(shí)候還是有些業(yè)務(wù)場(chǎng)景可能需要自定義conditon。這里就來以判斷上下文某個(gè)屬性值來擴(kuò)展condition。
最開始看到@Conditional注解是只有一個(gè)Condition類來指定出來?xiàng)l件判斷邏輯,沒有額外的配置項(xiàng)。這里要判斷某個(gè)property必須要指定property的key和value,所以第一步先自定義一個(gè)注解
@Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE, ElementType.METHOD }) @Conditional(PropertyConditionMatcher.class) public @interface MyPropertyCondition { String name(); String value(); }
這里自定義注解PropertyConditionMatcher兩個(gè)屬性name用來指定property的key,value用來指定property的value。除此之外我們自定義的注解還用@Conditional來修飾,這樣才能我們自定義的注解才能被當(dāng)作@Conditional來處理。然后來看我們的condition處理類PropertyConditionMatcher。
public class PropertyConditionMatcher implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(MyPropertyCondition.class.getName()); String propName = (String) annotationAttributes.get("name"); Object value = annotationAttributes.get("value"); String property = context.getEnvironment().getProperty(propName); if(property != null && property.equals(value)){ return true; } return false; } }
這里還是實(shí)現(xiàn)了Condition接口。然后首先從metadata中獲取配置的property名稱和value,然后從context的Environment根據(jù)前面的property名獲取當(dāng)前環(huán)境對(duì)應(yīng)值,兩個(gè)value進(jìn)行對(duì)比相等來判斷是否滿足條件。
然后具體條件bean上配置MyPropertyCondition。
@Service @MyPropertyCondition(name = "condation.enable",value = "true") public class ConditionService { }
這樣當(dāng)我們?cè)趐roperties文件中配置condation.enable=true時(shí),ConditionService就會(huì)創(chuàng)建為一個(gè)bean,否則不會(huì)創(chuàng)建。
以上就是Spring使用@Conditional進(jìn)行條件裝配的實(shí)現(xiàn)的詳細(xì)內(nèi)容,更多關(guān)于Spring @Conditional條件裝配的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java內(nèi)存異常使用導(dǎo)致full?gc頻繁
Full?GC是Java虛擬機(jī)中垃圾回收的一種方式,它會(huì)暫停應(yīng)用程序所有的線程并清理整個(gè)堆內(nèi)存。頻繁的Full?GC會(huì)導(dǎo)致應(yīng)用程序的性能下降,甚至出現(xiàn)長(zhǎng)時(shí)間的停頓。Java內(nèi)存異常使用常常是Full?GC頻繁出現(xiàn)的原因之一,如使用大量的靜態(tài)變量、內(nèi)存泄漏等。2023-04-04詳解Java正則表達(dá)式中Pattern類和Matcher類
java.util.regex是一個(gè)用正則表達(dá)式所訂制的模式來對(duì)字符串進(jìn)行匹配工作的類庫(kù)包。包括兩個(gè)類Pattern和Matcher Pattern,Pattern是一個(gè)正則表達(dá)式經(jīng)編譯后的表現(xiàn)模式。Matcher對(duì)象是一個(gè)狀態(tài)機(jī)器,它依據(jù)Pattern對(duì)象做為匹配模式對(duì)字符串展開匹配檢查。2016-12-12Springboot之restTemplate配置及使用方式
這篇文章主要介紹了Springboot之restTemplate配置及使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-04-04java Class文件內(nèi)部結(jié)構(gòu)解析過程詳解
java class的文件結(jié)構(gòu),java class文件結(jié)構(gòu)是基于字節(jié)流的,用unicode進(jìn)行編碼,下面說說java Class文件內(nèi)部結(jié)構(gòu)分析2013-11-11Eclipse可視化插件WindowBuilder的安裝方法
這篇文章主要介紹了Eclipse可視化插件WindowBuilder的安裝方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06mybatis使用foreach標(biāo)簽進(jìn)行嵌套插入
數(shù)據(jù)庫(kù)插入操作常見于多層架構(gòu)設(shè)計(jì)中,本文提供了一個(gè)具體的實(shí)現(xiàn)方案,涉及三層實(shí)體類結(jié)構(gòu),第一層實(shí)體類負(fù)責(zé)基本數(shù)據(jù)結(jié)構(gòu)的定義,第二層和第三層實(shí)體類則提供更詳細(xì)的業(yè)務(wù)邏輯處理,同時(shí),文章還介紹了相應(yīng)的mapper接口和配置文件設(shè)置2024-09-09使用Feign調(diào)用時(shí)添加驗(yàn)證信息token到請(qǐng)求頭方式
這篇文章主要介紹了使用Feign調(diào)用時(shí)添加驗(yàn)證信息token到請(qǐng)求頭方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03教你通過B+Tree平衡多叉樹理解InnoDB引擎的聚集和非聚集索引
大家都知道B+Tree是從二叉樹演化而來,在這之前我們來先了解二叉樹、平衡二叉樹、平衡多叉樹,這篇文章主要介紹了通過B+Tree平衡多叉樹理解InnoDB引擎的聚集和非聚集索引,需要的朋友可以參考下2022-01-01