Spring使用@Conditional進(jìn)行條件裝配的實(shí)現(xiàn)
在spring中有些bean需要滿足某些環(huán)境條件才創(chuàng)建某個(gè)bean,這個(gè)時(shí)候可以在bean定義上使用@Conditional注解來(lái)修飾。@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)?,context和metadata。從context可以獲取beanFactory和environment信息,從metadata可以獲取當(dāng)前bean上所有注解配置信息。通過(guò)這兩個(gè)參數(shù)可以獲取到很多信息了,這里就可以根據(jù)上下文來(lái)進(jìn)行判斷。不如beanFacotry是否有某個(gè)bean,當(dāng)前環(huán)境的profile信息,某個(gè)屬性的配置信息等等。
看到這里你是否想到了些什么,沒(méi)錯(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我們沒(méi)有顯示聲明可以直接拿來(lái)注入使用了吧。
condition的擴(kuò)展
雖然springboot也封裝了很多場(chǎng)景的condition注解,但是難免有時(shí)候還是有些業(yè)務(wù)場(chǎng)景可能需要自定義conditon。這里就來(lái)以判斷上下文某個(gè)屬性值來(lái)擴(kuò)展condition。
最開(kāi)始看到@Conditional注解是只有一個(gè)Condition類來(lái)指定出來(lái)?xiàng)l件判斷邏輯,沒(méi)有額外的配置項(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用來(lái)指定property的key,value用來(lái)指定property的value。除此之外我們自定義的注解還用@Conditional來(lái)修飾,這樣才能我們自定義的注解才能被當(dāng)作@Conditional來(lái)處理。然后來(lái)看我們的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ì)比相等來(lái)判斷是否滿足條件。
然后具體條件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)文章
springboot+knife4j+nacos實(shí)踐
這篇文章主要介紹了springboot+knife4j+nacos實(shí)踐,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-06-06
Spring cloud alibaba之Gateway網(wǎng)關(guān)功能特征詳解
spring cloud gateway是spring cloud推出的第二代網(wǎng)關(guān),是由WebFlux+Netty+Reactor實(shí)現(xiàn)的響應(yīng)式的API網(wǎng)關(guān),它不能在傳統(tǒng)的servlet容器中工作,也不能構(gòu)建成war包,接下來(lái)通過(guò)本文給大家分享Spring cloud alibaba--Gateway網(wǎng)關(guān),需要的朋友可以參考下2021-08-08
詳解Java中的時(shí)間處理與時(shí)間標(biāo)準(zhǔn)
這篇文章主要為大家詳細(xì)介紹了三個(gè)時(shí)間標(biāo)準(zhǔn)GMT,CST,UTC的規(guī)定,以及Java進(jìn)行時(shí)間處理的相關(guān)知識(shí),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-09-09
Spring使用注解進(jìn)行對(duì)象注入的示例詳解
獲取?Bean?對(duì)象也叫做對(duì)象裝配,就是把對(duì)象取出來(lái)放到某個(gè)類中,有時(shí)候也叫對(duì)象注入,常見(jiàn)有關(guān)對(duì)象注入的注解有兩個(gè),一個(gè)是@Autowired,另外一個(gè)是@Resource,下面就來(lái)講講它們的具體使用吧2023-07-07
Java基于的Spire.Doc實(shí)現(xiàn)Word文檔(DOC/DOCX)文字水印添加
這篇文章主要為大家詳細(xì)介紹了Java基于的Spire.Doc實(shí)現(xiàn)Word文檔(DOC/DOCX)文字水印添加的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2026-02-02
Java8函數(shù)式接口的基礎(chǔ)學(xué)習(xí)教程
這篇文章主要給大家介紹了關(guān)于Java8函數(shù)式接口基礎(chǔ)學(xué)習(xí)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04

