SpringBoot中condition注解的使用方式
在項目中,有時會遇到我們的Configuration、Bean、Service等等的bean組件需要依條件按需加載的情況。
springboot中提供了一系列@Condition* 注解來處理有條件注入的情況。
說明
Spring4中增加了@Condition annotation, 使用該Annotation之后,在做依賴注入的時候,會檢測是否滿足某個條件來決定是否注入某個類。
springboot基于spring4的這個注解實現(xiàn)了多個用于判斷的條件注解,如果我們在使用中這些注解無法滿足我們的要求還可以使用@Conditional自定義條件注解
常用的條件注解
條件注解 | 對應(yīng)的Condition 處理類 | 處理邏輯 |
---|---|---|
@ConditionalOnBean | OnBeanCondition | Spring容器中是否存在對應(yīng)的實例??梢酝ㄟ^實例的類型、類名、注解、昵稱去容器中查找(可以配置從當(dāng)前容器中查找或者父容器中查找或者兩者一起查找) |
@ConditionalOnClass | OnClassCondition | 類加載器中是否存在對應(yīng)的類??梢酝ㄟ^Class指定(value屬性)或者Class的全名指定(name屬性)如果是多個類或者多個類名的話,關(guān)系是”與”關(guān)系,也就是說這些類或者類名都必須同時在類加載器中存在 |
@ConditionalOnExpression | OnExpressionCondition | 判斷SpEL 表達(dá)式是否成立 |
@ConditionalOnMissingBean | OnBeanCondition | Spring容器中是否缺少對應(yīng)的實例??梢酝ㄟ^實例的類型、類名、注解、昵稱去容器中查找(可以配置從當(dāng)前容器中查找或者父容器中查找或者兩者一起查找) |
@ConditionalOnMissingClass | OnClassCondition | 跟ConditionalOnClass的處理邏輯一樣,只是條件相反,在類加載器中不存在對應(yīng)的類 |
@ConditionalOnProperty | OnPropertyCondition | 應(yīng)用環(huán)境中的屬性是否存在。提供prefix、name、havingValue以及matchIfMissing屬性。prefix表示屬性名的前綴,name是屬性名,havingValue是具體的屬性值,matchIfMissing是個boolean值,如果屬性不存在,這個matchIfMissing為true的話,會繼續(xù)驗證下去,否則屬性不存在的話直接就相當(dāng)于匹配不成功 |
@ConditionalOnResource | OnResourceCondition | 是否存在指定的資源文件。只有一個屬性resources,是個String數(shù)組。會從類加載器中去查詢對應(yīng)的資源文件是否存在 |
@ConditionalOnSingleCandidate | OnBeanCondition | Spring容器中是否存在且只存在一個對應(yīng)的實例。只有3個屬性value、type、search。跟ConditionalOnBean中的這3種屬性值意義一樣 |
@ConditionalOnWebApplication | OnWebApplicationCondition | 應(yīng)用程序是否是Web程序,沒有提供屬性,只是一個標(biāo)識。會從判斷Web程序特有的類是否存在,環(huán)境是否是Servlet環(huán)境,容器是否是Web容器等 |
舉例
例子 | 說明 |
---|---|
@ConditionalOnBean(javax.sql.DataSource.class) | Spring容器或者所有父容器中需要存在至少一個javax.sql.DataSource類的實例 |
@ConditionalOnClass({ Configuration.class,FreeMarkerConfigurationFactory.class }) | 類加載器中必須存在Configuration和FreeMarkerConfigurationFactory這兩個類 |
@ConditionalOnExpression(“’${server.host}’==’localhost’”) | server.host配置項的值需要是localhost |
ConditionalOnJava(JavaVersion.EIGHT) | Java版本至少是8 |
@ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT) | Spring當(dāng)前容器中不存在ErrorController類型的bean |
@ConditionalOnMissingClass(“GenericObjectPool”) | 類加載器中不能存在GenericObjectPool這個類 |
@ConditionalOnNotWebApplication | 必須在非Web應(yīng)用下才會生效 |
@ConditionalOnProperty(prefix = “spring.aop”, name = “auto”, havingValue = “true”, matchIfMissing = true) | 應(yīng)用程序的環(huán)境中必須有spring.aop.auto這項配置,且它的值是true或者環(huán)境中不存在spring.aop.auto配置(matchIfMissing為true) |
@ConditionalOnResource(resources=”mybatis.xml”) | 類加載路徑中必須存在mybatis.xml文件 |
@ConditionalOnSingleCandidate(PlatformTransactionManager.class) | Spring當(dāng)前或父容器中必須存在PlatformTransactionManager這個類型的實例,且只有一個實例 |
@ConditionalOnWebApplication | 必須在Web應(yīng)用下才會生效 |
自定義條件注解
實現(xiàn)條件化注解我們需要兩個類
- 自定義注解類
- 定義注解,指定判斷用的條件類
- 條件類
- 實現(xiàn)org.springframework.context.annotation.Condition接口,定義判斷條件
舉例說明
1.定義注解類MyConditionalOnProperty
要使用注解@Conditional(MyOnPropertyCondition.class)
,MyOnPropertyCondition為我們要定義的條件類
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) @Documented @Conditional(MyOnPropertyCondition.class) public @interface MyConditionalOnProperty { String value(); String prefix() default ""; String havingValue() default ""; boolean matchIfMissing() default false; boolean relaxedNames() default true; //TODO ADD ONE PROPERTY String havingValue() default ""; }
2.定義條件類:
public class MyOnPropertyCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(MyConditionalOnProperty.class.getName()); String propertyName = (String) annotationAttributes.get("value"); String value = annotationAttributes.get("havingValue"); String propertyValue = context.getEnvironment().getProperty(propertyName); if (propertyValue.equalsIgnoreCase(value)) { return true; } return false; } }
3.調(diào)用
@Configuration public class MyConfig { @Bean @MyConditionalOnProperty(value = "env",havingValue = "dev") public Person person(){ log.info("創(chuàng)建Bean"); return new Person(); } }
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
idea 在springboot中使用lombok插件的方法
這篇文章主要介紹了idea 在springboot中使用lombok的相關(guān)資料,通過代碼給大家介紹在pom.xml中引入依賴的方法,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2021-08-08使用Spring Cache時設(shè)置緩存鍵的注意事項詳解
在現(xiàn)代的Web應(yīng)用中,緩存是提高系統(tǒng)性能和響應(yīng)速度的重要手段之一,Spring框架提供了強大的緩存支持,通過??@Cacheable??、??@CachePut??、??@CacheEvict??等注解可以方便地實現(xiàn)緩存功能,本文給大家介紹了使用Spring Cache時設(shè)置緩存鍵的注意事項2025-01-01在?Spring?Boot?中使用?Quartz?調(diào)度作業(yè)的示例詳解
這篇文章主要介紹了在?Spring?Boot?中使用?Quartz?調(diào)度作業(yè)的示例詳解,在本文中,我們將看看如何使用Quartz框架來調(diào)度任務(wù),Quartz支持在特定時間運行作業(yè)、重復(fù)作業(yè)執(zhí)行、將作業(yè)存儲在數(shù)據(jù)庫中以及Spring集成,需要的朋友可以參考下2022-07-07SpringCloud GateWay動態(tài)路由用法
網(wǎng)關(guān)作為所有項目的入口,不希望重啟,因此動態(tài)路由是必須的,動態(tài)路由主要通過RouteDefinitionRepository接口實現(xiàn),其默認(rèn)的實現(xiàn)是InMemoryRouteDefinitionRepository,即在內(nèi)存中存儲路由配置,可基于這個map對象操作,動態(tài)路由的實現(xiàn)方案有兩種2024-10-10springboot配置文件中使用${}注入值的兩種方式小結(jié)
這篇文章主要介紹了springboot配置文件中使用${}注入值的兩種方式小結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03