<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Spring Boot 條件注解

          共 9783字,需瀏覽 20分鐘

           ·

          2022-01-02 14:42

          ?SpringBoot條件注解@Conditional,可用于根據(jù)某個(gè)特定的條件來(lái)判斷是否需要?jiǎng)?chuàng)建某個(gè)特定的Bean。SpringBoot自動(dòng)配置功能里面就大量的使用了條件注解。接下來(lái)我們就對(duì)@Conditional的使用做一個(gè)簡(jiǎn)單的介紹。

          ? ? ? ?@Conditional注解需要和Condition接口搭配一起使用。通過(guò)對(duì)應(yīng)Condition接口來(lái)告知是否滿足匹配條件。


          @Target({ElementType.TYPE,?ElementType.METHOD})
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          public?@interface?Conditional?{

          ????/**
          ?????*?所有用于匹配的Condition接口(實(shí)現(xiàn)該接口的類),只有這些類都返回true才認(rèn)為是滿足條件
          ?????*/

          ????Classextends
          ?Condition>[]?value();

          }


          ? ? ? ?@Conditional注解可以添加在@Configuration、@Component、@Service等修飾的類上用于控制對(duì)應(yīng)的Bean是否需要?jiǎng)?chuàng)建,或者添加在@Bean修飾的方法上用于控制方法對(duì)應(yīng)的Bean是否需要?jiǎng)?chuàng)建。

          @Conditional添加在@Configuration修飾的類上,用于控制該類和該類里面所有添加的@Bean方法對(duì)應(yīng)的Bean是否需要?jiǎng)?chuàng)建。

          一 @Conditional擴(kuò)展注解

          ? ? ? ?為了方便我們的使用Spring Boot對(duì)@Conditional條件注解做了一些擴(kuò)展,提供了一些很實(shí)用的擴(kuò)展性條件注解。

          條件注解Condition處理類實(shí)例解釋
          @ConditionalOnBeanOnBeanCondition@ConditionalOnBean(DataSource.class)Spring容器中不存在對(duì)應(yīng)的實(shí)例生效
          @ConditionalOnMissingBeanOnBeanCondition@ConditionalOnMissingBean(name = "redisTemplate")Spring容器中不存在對(duì)應(yīng)的實(shí)例生效
          @ConditionalOnSingleCandidateOnBeanCondition@ConditionalOnSingleCandidate(FilteringNotifier.class)Spring容器中是否存在且只存在一個(gè)對(duì)應(yīng)的實(shí)例,或者雖然有多個(gè)但 是指定首選的Bean生效
          @ConditionalOnClassOnClassCondition@ConditionalOnClass(RedisOperations.class)類加載器中存在對(duì)應(yīng)的類生效
          @ConditionalOnMissingClassOnClassCondition@ConditionalOnMissingClass(RedisOperations.class)類加載器中不存在對(duì)應(yīng)的類生效
          @ConditionalOnExpressionOnExpressionCondition@ConditionalOnExpression(“’${server.host}’==’localhost’”)判斷SpEL 表達(dá)式成立生效
          @ConditionalOnJavaOnJavaCondition@ConditionalOnJava(JavaVersion.EIGHT)指定Java版本符合要求生效
          @ConditionalOnPropertyOnPropertyCondition@ConditionalOnProperty(prefix = “spring.aop”, name = “auto”, havingValue = “true”, matchIfMissing = true)應(yīng)用環(huán)境中的屬性滿足條件生效
          @ConditionalOnResourceOnResourceCondition@ConditionalOnResource(resources=”mybatis.xml”)存在指定的資源文件生效
          @ConditionalOnWebApplicationOnWebApplicationCondition
          當(dāng)前應(yīng)用是Web應(yīng)用生效
          @ConditionalOnNotWebApplicationOnWebApplicationCondition
          當(dāng)前應(yīng)用不是Web應(yīng)用生效

          ? ? ? ?上面的擴(kuò)展注解我們可以簡(jiǎn)單的分為以下幾類:

          • Bean作為條件:@ConditionalOnBean、@ConditionalOnMissingBean、@ConditionalOnSingleCandidate。

          • 類作為條件:@ConditionalOnClass、@ConditionalOnMissingClass。

          • SpEL表達(dá)式作為條件:@ConditionalOnExpression。

          • JAVA版本作為條件: @ConditionalOnJava

          • 配置屬性作為條件:@ConditionalOnProperty。

          • 資源文件作為條件:@ConditionalOnResource。

          • 是否Web應(yīng)用作為判斷條件:@ConditionalOnWebApplication、@ConditionalOnNotWebApplication。

          1.1 Bean作為條件

          1.1.1 @ConditionalOnBean

          ? ? ? ?@ConditionalOnBean對(duì)應(yīng)的Condition處理類是OnBeanCondition。如果Spring容器里面存在指定的Bean則生效。

          @ConditionalOnBean配置參數(shù)

          @Target({?ElementType.TYPE,?ElementType.METHOD?})
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          @Conditional(OnBeanCondition.class)
          public?@interface?ConditionalOnBean?{

          ????/**
          ?????*?需要作為條件的類的Class對(duì)象數(shù)組
          ?????*/

          ????Class[]?value()?default?{};

          ????/**
          ?????*?需要作為條件的類的Name,?Class.getName()
          ?????*/

          ????String[]?type()?default?{};

          ????/**
          ?????*?(用于指定注解修飾的Bean)條件所需的注解類
          ?????*/

          ????Classextends
          ?Annotation>[]?annotation()?default?{};

          ????/**
          ?????*?Spring容器中Bean的名字
          ?????*/

          ????String[]?name()?default?{};

          ????/**
          ?????*?搜索容器層級(jí),當(dāng)前容器,父容器
          ?????*/

          ????SearchStrategy?search()?default?SearchStrategy.ALL;

          ????/**
          ?????*?可能在其泛型參數(shù)中包含指定Bean類型的其他類
          ?????*/

          ????Class[]?parameterizedContainer()?default?{};

          }


          1.1.2 @ConditionalOnMissingBean

          ? ? ? ?@ConditionalOnMissingBean對(duì)應(yīng)的Condition實(shí)現(xiàn)類是OnBeanCondition。如果Spring容器里面不存在指定的Bean則生效。

          @ConditionalOnMissingBean配置參數(shù)


          @Target({?ElementType.TYPE,?ElementType.METHOD?})
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          @Conditional(OnBeanCondition.class)
          public?@interface?ConditionalOnMissingBean?{

          ????/**
          ?????*?需要作為條件的類的Class對(duì)象數(shù)組
          ?????*/

          ????Class[]?value()?default?{};

          ????/**
          ?????*?需要作為條件的類的Name,?Class.getName()
          ?????*/

          ????String[]?type()?default?{};

          ????/**
          ?????*?匹配Bean的時(shí)候需要忽視的Class對(duì)象數(shù)組,一般是父類
          ?????*?@ConditionalOnMissingBean(value?=?JdbcFactory.class,?ignored?=?MySqlDefaultFactory.class)
          ?????*/

          ????Class[]?ignored()?default?{};

          ????/**
          ?????*?匹配Bean的時(shí)候需要忽視的類的Name,?Class.getName()
          ?????*/

          ????String[]?ignoredType()?default?{};

          ????/**
          ?????*?(用于指定注解修飾的Bean)條件所需的注解類
          ?????*/

          ????Classextends
          ?Annotation>[]?annotation()?default?{};

          ????/**
          ?????*?Spring容器中Bean的名字
          ?????*/

          ????String[]?name()?default?{};

          ????/**
          ?????*?搜索容器層級(jí),當(dāng)前容器,父容器
          ?????*/

          ????SearchStrategy?search()?default?SearchStrategy.ALL;

          ????/**
          ?????*?可能在其泛型參數(shù)中包含指定Bean類型的其他類
          ?????*/

          ????Class[]?parameterizedContainer()?default?{};

          }



          ? ? ? ?比如如下的實(shí)例,當(dāng)容器里面不存在redisTemplate對(duì)應(yīng)的Bean的時(shí)候,就會(huì)創(chuàng)建一個(gè)RedisTemplate添加到容器里面去。


          @Bean
          ????@ConditionalOnMissingBean(name?=?"redisTemplate")
          ????public?RedisTemplate<Object,?Object>?redisTemplate(RedisConnectionFactory?redisConnectionFactory)
          ????????????throws?UnknownHostException?{
          ????????RedisTemplate<Object,?Object>?template?=?new?RedisTemplate<>();
          ????????template.setConnectionFactory(redisConnectionFactory);
          ????????return?template;
          ????}


          1.1.3 @ConditionalOnSingleCandidate

          ? ? ? ?@ConditionalOnSingleCandidate對(duì)應(yīng)的Condition處理類是OnBeanCondition。如果當(dāng)指定Bean在容器中只有一個(gè),或者雖然有多個(gè)但是指定首選Bean的時(shí)候則生效。

          @ConditionalOnSingleCandidate配置參數(shù)


          @Target({?ElementType.TYPE,?ElementType.METHOD?})
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          @Conditional(OnBeanCondition.class)
          public?@interface?ConditionalOnSingleCandidate?{

          ????/**
          ?????*?需要作為條件的類的Class對(duì)象
          ?????*/

          ????Class?value()?default?Object.class;

          ????/**
          ?????*?需要作為條件的類的Name,?Class.getName()
          ?????*/

          ????String?type()?default?"";

          ????/**
          ?????*?搜索容器層級(jí),當(dāng)前容器,父容器
          ?????*/

          ????SearchStrategy?search()?default?SearchStrategy.ALL;

          }


          1.2 類作為條件

          1.2.1 @ConditionalOnClass

          ? ? ? ?@ConditionalOnClass對(duì)應(yīng)的Condition處理類是OnClassCondition。如果當(dāng)前類路徑下面有指定的類的時(shí)候則生效。

          @ConditionalOnClass配置屬性介紹


          @Target({?ElementType.TYPE,?ElementType.METHOD?})
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          @Conditional(OnClassCondition.class)
          public?@interface?ConditionalOnClass?{

          ????/**
          ?????*?需要作為條件的類的Class對(duì)象數(shù)組
          ?????*/

          ????Class[]?value()?default?{};

          ????/**
          ?????*?需要作為條件的類的Name,?Class.getName()
          ?????*/

          ????String[]?name()?default?{};

          }



          1.2.2 @ConditionalOnMissingClass

          ? ? ? ?@ConditionalOnMissingClass對(duì)應(yīng)的Condition處理類是OnClassCondition。如果當(dāng)前類路徑下面沒(méi)有指定的類的時(shí)候則生效。


          @Target({?ElementType.TYPE,?ElementType.METHOD?})
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          @Conditional(OnClassCondition.class)
          public?@interface?ConditionalOnMissingClass?{

          ????/**
          ?????*?需要作為條件的類的Name,?Class.getName()
          ?????*/

          ????String[]?value()?default?{};

          }



          1.3 ?SpEL表達(dá)式作為條件

          ? ? ? ?@ConditionalOnExpression對(duì)應(yīng)的Condition處理類是OnExpressionCondition。只有當(dāng)SpEL表達(dá)式滿足條件的時(shí)候則生效。


          @Retention(RetentionPolicy.RUNTIME)
          @Target({?ElementType.TYPE,?ElementType.METHOD?})
          @Documented
          @Conditional(OnExpressionCondition.class)
          public?@interface?ConditionalOnExpression?{

          ????/**
          ?????*?要作為條件的SpEL表達(dá)式
          ?????*/

          ????String?value()?default?"true";

          }


          ? ? ? ?例如@ConditionalOnExpression("${test.enabled:true}"),只有當(dāng)配置文件里面存在test.enabled: true的時(shí)候則生效。

          更加詳細(xì)的用法可以去看下SpEL表達(dá)式的使用。

          1.4 ?JAVA版本作為判斷條件

          ? ? ? ?@ConditionalOnJava對(duì)應(yīng)的Condition處理類是OnJavaCondition。只有當(dāng)指定的JAVA版本條件滿足的時(shí)候,才會(huì)創(chuàng)建對(duì)應(yīng)的Bean。


          @Target({?ElementType.TYPE,?ElementType.METHOD?})
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          @Conditional(OnJavaCondition.class)
          public?@interface?ConditionalOnJava?{

          ????/**
          ?????*?比較方式,Range.EQUAL_OR_NEWER:當(dāng)前版本等于或高于、Range.OLDER_THAN:當(dāng)前版本老于,越早的版本越老
          ?????*/

          ????Range?range()?default?Range.EQUAL_OR_NEWER;

          ????/**
          ?????*?指定JAVA版本
          ?????*/

          ????JavaVersion?value();

          ????/**
          ?????*?Range?options.
          ?????*/

          ????enum?Range?{

          ????????/**
          ?????????*?Equal?to,?or?newer?than?the?specified?{@link?JavaVersion}.
          ?????????*/

          ????????EQUAL_OR_NEWER,

          ????????/**
          ?????????*?Older?than?the?specified?{@link?JavaVersion}.
          ?????????*/

          ????????OLDER_THAN

          ????}

          }


          1.5 配置屬性作為判斷條件

          ? ? ? ?@ConditionalOnProperty對(duì)應(yīng)的Condition實(shí)現(xiàn)類OnPropertyCondition。只有當(dāng)對(duì)應(yīng)的配置屬性和給定條件的值相等的時(shí)候則生效。


          @Retention(RetentionPolicy.RUNTIME)
          @Target({?ElementType.TYPE,?ElementType.METHOD?})
          @Documented
          @Conditional(OnPropertyCondition.class)
          public?@interface?ConditionalOnProperty?{

          ????/**
          ?????*?對(duì)應(yīng)property名稱的值
          ?????*/
          ????String[]?value()?default?{};
          ????String[]?name()?default?{};


          ????/**
          ?????*?property名稱的前綴,可有可無(wú)
          ?????*/
          ????String?prefix()?default?"";

          ????/**
          ?????*?與name組合使用,比較獲取到的屬性值與havingValue給定的值是否相同,相同才加載配置
          ?????*/
          ????String?havingValue()?default?"";

          ????/**
          ?????*?缺少該property時(shí)是否可以加載。如果為true,沒(méi)有該property也會(huì)正常加載;反之報(bào)錯(cuò)
          ?????*/
          ????boolean?matchIfMissing()?default?false;

          }


          ? ? ? ?@ConditionalOnProperty(prefix = “spring.aop”, name = “auto”, havingValue = “true”)表示當(dāng)配置文件里面spring.aop.auto=true的時(shí)候才會(huì)加載對(duì)應(yīng)的Bean。

          1.6 資源文件是否存在作為判斷條件

          ? ? ? ?@ConditionalOnResource對(duì)應(yīng)的Condition處理類OnResourceCondition。只有當(dāng)指定的資源文件出現(xiàn)在classpath中則生效。

          @ConditionalOnResource配置屬性


          @Target({?ElementType.TYPE,?ElementType.METHOD?})
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          @Conditional(OnResourceCondition.class)
          public?@interface?ConditionalOnResource?{

          ????/**
          ?????*?要作為判斷條件的資源文件名稱??@ConditionalOnResource(resources=”mybatis.xml”)
          ?????*/

          ????String[]?resources()?default?{};

          }



          1.7 是否Web應(yīng)用作為判斷條件

          1.7.1 @ConditionalOnWebApplication

          ? ? ? ?@ConditionalOnWebApplication對(duì)應(yīng)的Condition處理類是OnWebApplicationCondition。只有當(dāng)當(dāng)前項(xiàng)目是Web項(xiàng)目的時(shí)候則生效。


          @Target({?ElementType.TYPE,?ElementType.METHOD?})
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          @Conditional(OnWebApplicationCondition.class)
          public?@interface?ConditionalOnWebApplication?{

          ????/**
          ?????*?需要作為條件的Web應(yīng)用程序的必需類型
          ?????*/

          ????Type?type()?default?Type.ANY;

          ????/**
          ?????*?Available?application?types.
          ?????*/

          ????enum?Type?{

          ????????/**
          ?????????*?任何web應(yīng)用都將匹配
          ?????????*/

          ????????ANY,

          ????????/**
          ?????????*?僅基于servlet的Web應(yīng)用程序?qū)⑵ヅ?br>?????????*/

          ????????SERVLET,

          ????????/**
          ?????????*?僅基于反應(yīng)式的Web應(yīng)用程序?qū)⑵ヅ?br>?????????*/

          ????????REACTIVE

          ????}

          }


          1.7.2 @ConditionalOnNotWebApplication

          ? ? ? ?@ConditionalOnNotWebApplication對(duì)應(yīng)的Condition處理類是OnWebApplicationCondition。只有當(dāng)當(dāng)前項(xiàng)目不是Web項(xiàng)目的時(shí)候則生效。


          @Target({?ElementType.TYPE,?ElementType.METHOD?})
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          @Conditional(OnWebApplicationCondition.class)
          public?@interface?ConditionalOnNotWebApplication?{

          }


          二 @Conditional自定義

          ? ? ? ?上面介紹每個(gè)擴(kuò)展注解的時(shí)候都特意提到了每個(gè)注解對(duì)應(yīng)的Condition實(shí)現(xiàn)類。其實(shí)我們可以仿照這些Condition實(shí)現(xiàn)類來(lái)實(shí)現(xiàn)我們自己的@Conditional注解。下面我們同個(gè)兩個(gè)簡(jiǎn)單的實(shí)例來(lái)看下怎么實(shí)現(xiàn)自己的@Conditional擴(kuò)展注解。

          2.1 判斷是否配置指定屬性

          ? ? ? ?注意,和@ConditionalOnProperty不一樣哦,@ConditionalOnProperty是判斷是否有屬性并且判斷值是否等于我們指定的值。我們要實(shí)現(xiàn)的注解只判斷有沒(méi)有配置屬性,不管屬性對(duì)應(yīng)的值。

          ? ? ? ?擴(kuò)展注解ConditionalOnPropertyExist。指定我們的Condition實(shí)現(xiàn)類OnPropertyExistCondition。并且指定兩個(gè)參數(shù)。一個(gè)是參數(shù)name用于指定屬性。另一個(gè)參數(shù)exist用于指定是判斷存在還是不存在。


          @Retention(RetentionPolicy.RUNTIME)
          @Target({ElementType.TYPE,?ElementType.METHOD})
          @Documented
          @Conditional(OnPropertyExistCondition.class)
          public?@interface?ConditionalOnPropertyExist?{

          ????/**
          ?????*?配置文件里面對(duì)應(yīng)的key
          ?????*/

          ????String?name()?default?"";

          ????/**
          ?????*?是否有配置的時(shí)候判斷通過(guò)
          ?????*/

          ????boolean?exist()?default?true;

          }


          ? ? ? ?OnPropertyExistCondition類就是簡(jiǎn)單的判斷下屬性存在與否。


          public?class?OnPropertyExistCondition?implements?Condition?{
          ????@Override
          ????public?boolean?matches(ConditionContext?conditionContext,?AnnotatedTypeMetadata?annotatedTypeMetadata)?{
          ????????Map<String,?Object>?annotationAttributes?=?annotatedTypeMetadata.getAnnotationAttributes(ConditionalOnPropertyExist.class.getName());
          ????????if?(annotationAttributes?==?null)?{
          ????????????return?false;
          ????????}
          ????????String?propertyName?=?(String)?annotationAttributes.get("name");
          ????????boolean?values?=?(boolean)?annotationAttributes.get("exist");
          ????????String?propertyValue?=?conditionContext.getEnvironment().getProperty(propertyName);
          ????????if(values)?{
          ????????????return?!StringUtils.isEmpty(propertyValue);
          ????????}?else?{
          ????????????return?StringUtils.isEmpty(propertyValue);
          ????????}
          ????}
          }


          2.1 判斷是否配置指定屬性

          ? ? ? ?我們簡(jiǎn)單實(shí)現(xiàn)這樣一個(gè)功能,根據(jù)指定的系統(tǒng)加載不同的Bean。


          @Retention(RetentionPolicy.RUNTIME)
          @Target({ElementType.TYPE,?ElementType.METHOD})
          @Documented
          @Conditional(OnSystemCondition.class)
          public?@interface?ConditionalOnSystem?{

          ????/**
          ?????*?指定系統(tǒng)
          ?????*/

          ????SystemType?type()?default?SystemType.WINDOWS;

          ????/**
          ?????*?系統(tǒng)類型
          ?????*/

          ????enum?SystemType?{

          ????????/**
          ?????????*?windows系統(tǒng)
          ?????????*/

          ????????WINDOWS,

          ????????/**
          ?????????*?linux系統(tǒng)
          ?????????*/

          ????????LINUX,

          ????????/**
          ?????????*?mac系統(tǒng)
          ?????????*/

          ????????MAC

          ????}
          }
          public?class?OnSystemCondition?implements?Condition?{


          ????@Override
          ????public?boolean?matches(ConditionContext?context,?AnnotatedTypeMetadata?metadata)?{
          ????????Map<String,?Object>?annotationAttributes?=?metadata.getAnnotationAttributes(ConditionalOnSystem.class.getName());
          ????????if?(annotationAttributes?==?null)?{
          ????????????return?false;
          ????????}
          ????????ConditionalOnSystem.SystemType?systemType?=?(ConditionalOnSystem.SystemType)?annotationAttributes.get("type");
          ????????switch?(systemType)?{
          ????????????case?WINDOWS:
          ????????????????return?context.getEnvironment().getProperty("os.name").contains("Windows");
          ????????????case?LINUX:
          ????????????????return?context.getEnvironment().getProperty("os.name").contains("Linux?");
          ????????????case?MAC:
          ????????????????return?context.getEnvironment().getProperty("os.name").contains("Mac?");
          ????????}
          ????????return?false;
          ????}
          }


          作者:tuacy
          source:?//www.jianshu.com/p/e21b9079a23c

          喜歡,在看

          瀏覽 46
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  奇米影视7777久久精品 | 欧美啪啪自拍 | 操操操操操操 | 婷婷五月天电影 | 超碰青娱乐97 |