最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

springboot注解之@Conditional使用解析

 更新時(shí)間:2023年11月27日 10:50:40   作者:碼農(nóng)打工人  
這篇文章主要介紹了springboot注解之@Conditional使用解析,conditional 這個(gè)英文單詞翻譯過(guò)來(lái)是有條件的,所以 @Conditional 注解是作為條件存在的,如果滿足配置的條件則執(zhí)行,如果沒(méi)有滿足的話就不執(zhí)行,需要的朋友可以參考下

前言

conditional 這個(gè)英文單詞翻譯過(guò)來(lái)是有條件的,所以 @Conditional 注解是作為條件存在的,如果滿足配置的條件則執(zhí)行,如果沒(méi)有滿足的話就不執(zhí)行。

一、@Conditional

@Conditional 注解上面說(shuō)了是作為條件執(zhí)行的,那么是作為什么條件呢?這我們就需要知道 @Conditional 主要是作用在什么上面。

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
    Class<? extends Condition>[] value();
}

上面是 @Conditional 注解的源碼。我們看到注解的作用域是類、方法上。既然是作用在類上,即可以大體猜測(cè)到與 IOC 容器添加 bean 有關(guān)系。 事實(shí)上 @Conditional 注解一般與 @Configuration、@Bean 共同使用,也可以與 @Controller、@Service、@Component、@Repository 等等這些注解一起使用。所以 @Conditional 通常是作為是否添加這個(gè)對(duì)象為 IOC 容器組件的條件出現(xiàn)的。 既然知道 @Conditional 注解的作用,那么該注解應(yīng)該如何使用呢?我們看到該注解有一個(gè)必填的屬性 value,value 屬性的類型是 Condition 接口的實(shí)現(xiàn)類數(shù)組。我們看下 Condition 接口的源碼。

@FunctionalInterface
public interface Condition {
    boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}

Condition 接口只有一個(gè)抽象方法,返回 boolean 類型,可以知道返回為 true 則條件成立,返回 false 條件不成立。 方法中有兩個(gè)參數(shù),context 中包含容器、bean 工廠、類加載器、資源加載器、環(huán)境配置這五大核心屬性獲取方法,metadata 是注解的信息。 從這里我們也可以自己實(shí)現(xiàn) matches 方法,去自定義一個(gè)條件類。 自己去實(shí)現(xiàn) Condition 接口比較復(fù)雜,那么有沒(méi)有一些已經(jīng)實(shí)現(xiàn)好的常用的一些類呢?springboot 給我們提供了大量的這樣的實(shí)現(xiàn)類,讓我們基本不用自己去實(shí)現(xiàn) Condition 接口,就可以滿足日常的開(kāi)發(fā)。

二、@Conditional 的實(shí)現(xiàn)子注解

springboot 提供了大量的 @Conditional 子注解供我們使用,我們只需知道有哪些常用的子注解供我們使用即可。

springboot 提供的 @Conditional 子注解有:

  1. @ConditionalOnBean
  2. @ConditionalOnClass
  3. @ConditionalOnCloudPlatform
  4. @ConditionalOnExpression
  5. @ConditionalOnJava
  6. @ConditionalOnJndi
  7. @ConditionalOnMissingBean
  8. @ConditionalOnMissingClass
  9. @ConditionalOnNotWebApplication
  10. @ConditionalOnProperty
  11. @ConditionalOnResource
  12. @ConditionalOnSingleCandidate
  13. @ConditionalOnWarDeployment
  14. @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)類。 我們挑選一些日常常用的子注解做具體的說(shuō)明。

三、@ConditionalOnClass 注解

@ConditionalOnClass 的意思是以是否有該類為為條件。我們以 springboot 自動(dòng)配置 aop 的配置類做例子進(jìn)行解讀。 我們打開(kāi) springboot 的自動(dòng)配置包 spring-boot-autoconfigure-2.7.0.jar 包,找到 AopAutoConfiguration.class,打開(kāi)后有這么一段代碼。

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({Advice.class})
static class AspectJAutoProxyingConfiguration {
    AspectJAutoProxyingConfiguration() {
    }

    @Configuration(
        proxyBeanMethods = false
    )
    @EnableAspectJAutoProxy(
        proxyTargetClass = true
    )
    @ConditionalOnProperty(
        prefix = "spring.aop",
        name = {"proxy-target-class"},
        havingValue = "true",
        matchIfMissing = true
    )
    static class CglibAutoProxyConfiguration {
        CglibAutoProxyConfiguration() {
        }
    }

    @Configuration(
        proxyBeanMethods = false
    )
    @EnableAspectJAutoProxy(
        proxyTargetClass = false
    )
    @ConditionalOnProperty(
        prefix = "spring.aop",
        name = {"proxy-target-class"},
        havingValue = "false"
    )
    static class JdkDynamicAutoProxyConfiguration {
        JdkDynamicAutoProxyConfiguration() {
        }
    }
}

我們看到在內(nèi)部類 AspectJAutoProxyingConfiguration 上標(biāo)注了 @ConditionalOnClass({Advice.class}) 表示如果有 Advice.class 這個(gè)類則 AspectJAutoProxyingConfiguration 生效,否則就不生效。

那么我們測(cè)試以下。 首先我們測(cè)試以下沒(méi)有的時(shí)候。

@SpringBootApplication
public class SpringbootFunctionApplication {

    public static void main(String[] args) {
        // 返回 IOC 容器
        ConfigurableApplicationContext run = SpringApplication.run(SpringbootFunctionApplication.class, args);
        // 測(cè)試沒(méi)有 Advice.class 的時(shí)候,是否有 AspectJAutoProxyingConfiguration 組件
        try {
            // 反射獲取內(nèi)部類的 Class 對(duì)象
            Class<?> clazz = Class.forName("org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$AspectJAutoProxyingConfiguration");
            System.out.println(MessageFormat.format("容器中 AspectJAutoProxyingConfiguration 類型的組件個(gè)數(shù)有:{0}", run.getBeanNamesForType(clazz).length));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

結(jié)果為:

容器中 AspectJAutoProxyingConfiguration 類型的組件個(gè)數(shù)有:0

可以看到如果沒(méi)有 Advice.class 的時(shí)候,@ConditionalOnClass 標(biāo)簽做了攔截,沒(méi)有添加 AspectJAutoProxyingConfiguration 為組件。

我們看下如果導(dǎo)入 Advice.class 之后會(huì)有什么現(xiàn)象。

我們?cè)?pom 文件中導(dǎo)入 aspectj 依賴

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.19</version>
    <scope>runtime</scope>
</dependency>

最后執(zhí)行我們看到的結(jié)果為:

容器中 AspectJAutoProxyingConfiguration 類型的組件個(gè)數(shù)有:1

可以看到有了 Advice.class 之后,在容器添加 AspectJAutoProxyingConfiguration 作為 bean 的時(shí)候,通過(guò)了 @ConditionalOnClass 的校驗(yàn)。

四、@ConditionalOnMissingClass 注解

我們說(shuō)完了 @ConditionalOnClass,我們說(shuō)一下它的相反意思的注解:@ConditionalOnMissingClass。 @ConditionalOnMissingClass 是如果沒(méi)有這個(gè) class 類則執(zhí)行。我們同樣以 springboot 自動(dòng)配置 aop 的配置類做例子,不同的是我們選擇了 AopAutoConfiguration.class 中的另一個(gè)內(nèi)部類 ClassProxyingConfiguration。

@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingClass({"org.aspectj.weaver.Advice"})
@ConditionalOnProperty(
    prefix = "spring.aop",
    name = {"proxy-target-class"},
    havingValue = "true",
    matchIfMissing = true
)
static class ClassProxyingConfiguration {
    ClassProxyingConfiguration() {
    }

    @Bean
    static BeanFactoryPostProcessor forceAutoProxyCreatorToUseClassProxying() {
        return (beanFactory) -> {
            if (beanFactory instanceof BeanDefinitionRegistry) {
                BeanDefinitionRegistry registry = (BeanDefinitionRegistry)beanFactory;
                AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }

        };
    }
}

可以看到內(nèi)部類 ClassProxyingConfiguration 上面標(biāo)注了 @ConditionalOnMissingClass 標(biāo)簽,條件是 org.aspectj.weaver.Advice 字符串,代表沒(méi)有該類則通過(guò)。

上面已經(jīng)引入了 aspectjweaver jar 包,我們看看容器中有沒(méi)有 ClassProxyingConfiguration 這個(gè) bean。

@SpringBootApplication
public class SpringbootFunctionApplication {

    public static void main(String[] args) {
        // 返回 IOC 容器
        ConfigurableApplicationContext run = SpringApplication.run(SpringbootFunctionApplication.class, args);
        // 測(cè)試有 Advice.class 的時(shí)候,是否有 ClassProxyingConfiguration 組件
        try {
            Class<?> clazz = Class.forName("org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$ClassProxyingConfiguration");
            System.out.println(MessageFormat.format("容器中 ClassProxyingConfiguration 類型的組件個(gè)數(shù)有:{0}", run.getBeanNamesForType(clazz).length));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

}

結(jié)果為:

容器中 ClassProxyingConfiguration 類型的組件個(gè)數(shù)有:0

可以看出有 Advice.class 的時(shí)候 @ConditionalOnMissingClass 注解會(huì)判斷不通過(guò),不會(huì)注冊(cè) ClassProxyingConfiguration 為 bean。

反過(guò)來(lái)如果沒(méi)有 Advice.class 的時(shí)候會(huì)是什么樣子呢?

容器中 ClassProxyingConfiguration 類型的組件個(gè)數(shù)有:1

五、@ConditionalOnBean 與 @ConditionalOnMissingBean

上面我們看了注解 @ConditionalOnClass、@ConditionalOnMissingClass,我們將要看的注解 @ConditionalOnBean 與 @ConditionalOnMissingBean 其實(shí)意思也是相似的,只不過(guò)前兩個(gè)注解以是否有 class 類作為判斷條件,后兩個(gè)注解以容器中是否有組件 bean 作為判斷條件。 我們看一個(gè)例子

@Bean
@ConditionalOnBean({MultipartResolver.class})
@ConditionalOnMissingBean(name = {"multipartResolver"})
public MultipartResolver multipartResolver(MultipartResolver resolver) {
    return resolver;
}

這里 @ConditionalOnBean({MultipartResolver.class}) 如果容器中有 MultipartResolver 類型的 bean 則條件通過(guò)。 @ConditionalOnMissingBean(name = {“multipartResolver”}) 則表示如果容器中沒(méi)有 ID 為 multipartResolver 的 bean 則條件通過(guò)。 可以看出這段代碼的功能是,如果容器中有 MultipartResolver 這個(gè)類型的 bean 但 ID 名稱不是 multipartResolver,則把名稱改為 multipartResolver。

六、@ConditionalOnProperty 注解

@ConditionalOnProperty 注解是以項(xiàng)目中的配置作為條件確定是否注冊(cè)為 bean。 我們還是以 springboot 自動(dòng)配置 aop 的配置類 AopAutoConfiguration.class 中的子類 AspectJAutoProxyingConfiguration 做例子進(jìn)行解讀。

static class AspectJAutoProxyingConfiguration {
        AspectJAutoProxyingConfiguration() {
        }

        @Configuration(
            proxyBeanMethods = false
        )
        @EnableAspectJAutoProxy(
            proxyTargetClass = true
        )
        @ConditionalOnProperty(
            prefix = "spring.aop",
            name = {"proxy-target-class"},
            havingValue = "true",
            matchIfMissing = true
        )
        static class CglibAutoProxyConfiguration {
            CglibAutoProxyConfiguration() {
            }
        }

        @Configuration(
            proxyBeanMethods = false
        )
        @EnableAspectJAutoProxy(
            proxyTargetClass = false
        )
        @ConditionalOnProperty(
            prefix = "spring.aop",
            name = {"proxy-target-class"},
            havingValue = "false"
        )
        static class JdkDynamicAutoProxyConfiguration {
            JdkDynamicAutoProxyConfiguration() {
            }
        }
    }

可以看到 @ConditionalOnProperty 注解具有4個(gè)屬性 prefix(配置前綴)、name(配置名稱)、havingValue(匹配的值)、matchIfMissing(如果找不到這個(gè)配置的值則返回) 在 AspectJAutoProxyingConfiguration 中有兩個(gè)內(nèi)部類 CglibAutoProxyConfiguration、JdkDynamicAutoProxyConfiguration。 CglibAutoProxyConfiguration 上面標(biāo)注的注解 @ConditionalOnProperty 屬性匹配的值為 true,如果沒(méi)有該配置則默認(rèn)通過(guò)。 JdkDynamicAutoProxyConfiguration 上面標(biāo)注的注解 @ConditionalOnProperty 屬性匹配的值為 false,沒(méi)有 matchIfMissing 屬性。 我們進(jìn)行下面測(cè)試:

@SpringBootApplication(scanBasePackages = {"com.study.springbootfunction", "com.study.exclude"})
public class SpringbootFunctionApplication {

    public static void main(String[] args) {
        // 返回 IOC 容器
        ConfigurableApplicationContext run = SpringApplication.run(SpringbootFunctionApplication.class, args);
        // 是否包含 CglibAutoProxyConfiguration、JdkDynamicAutoProxyConfiguration
        try {
            Class<?> a = Class.forName("org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$AspectJAutoProxyingConfiguration$CglibAutoProxyConfiguration");
            Class<?> j = Class.forName("org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$AspectJAutoProxyingConfiguration$JdkDynamicAutoProxyConfiguration");
            System.out.println(MessageFormat.format("容器中 CglibAutoProxyConfiguration 類型的組件個(gè)數(shù)有:{0}", run.getBeanNamesForType(a).length));
            System.out.println(MessageFormat.format("容器中 JdkDynamicAutoProxyConfiguration 類型的組件個(gè)數(shù)有:{0}", run.getBeanNamesForType(j).length));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }
}

先不在項(xiàng)目中配置 spring.aop.proxy-target-class 運(yùn)行結(jié)果為:

容器中 CglibAutoProxyConfiguration 類型的組件個(gè)數(shù)有:1
容器中 JdkDynamicAutoProxyConfiguration 類型的組件個(gè)數(shù)有:0

能夠得出 如果屬性 matchIfMissing 不配置的話默認(rèn)為 false。 在項(xiàng)目中配置 spring.aop.proxy-target-class=true

spring:
  aop:
    proxy-target-class: true

運(yùn)行結(jié)果為:

容器中 CglibAutoProxyConfiguration 類型的組件個(gè)數(shù)有:1
容器中 JdkDynamicAutoProxyConfiguration 類型的組件個(gè)數(shù)有:0

如果在項(xiàng)目中配置 spring.aop.proxy-target-class=false

spring:
  aop:
    proxy-target-class: false

運(yùn)行結(jié)果為:

容器中 CglibAutoProxyConfiguration 類型的組件個(gè)數(shù)有:0
容器中 JdkDynamicAutoProxyConfiguration 類型的組件個(gè)數(shù)有:1

可以看出 @ConditionalOnProperty 屬性 havingValue 的值與項(xiàng)目中配置的值相匹配時(shí)為滿足條件,如果值不匹配的時(shí)候則條件不滿足。

七、@ConditionalOnWebApplication

如果是 web 應(yīng)用,則滿足條件。這個(gè)配置在 mvc 中的配置比較多,我們看下 mvc 中 DispatcherServlet 的自動(dòng)配置類。

@AutoConfigureOrder(-2147483648)
@AutoConfiguration(
    after = {ServletWebServerFactoryAutoConfiguration.class}
)
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@ConditionalOnClass({DispatcherServlet.class})
public class DispatcherServletAutoConfiguration {
}

我們看到 DispatcherServletAutoConfiguration 在是 servlet 的傳統(tǒng)項(xiàng)目中則成立,滿足條件。

到此這篇關(guān)于springboot注解之@Conditional使用解析的文章就介紹到這了,更多相關(guān)springboot注解@Conditional內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java設(shè)計(jì)模式--三種工廠模式詳解

    java設(shè)計(jì)模式--三種工廠模式詳解

    這篇文章主要為大家詳細(xì)介紹了Java設(shè)計(jì)模式之工廠模式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能給你帶來(lái)幫助
    2021-07-07
  • Java線程狀態(tài)運(yùn)行原理解析

    Java線程狀態(tài)運(yùn)行原理解析

    這篇文章主要介紹了Java線程狀態(tài)運(yùn)行原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • java 實(shí)現(xiàn)反射 json動(dòng)態(tài)轉(zhuǎn)實(shí)體類--fastjson

    java 實(shí)現(xiàn)反射 json動(dòng)態(tài)轉(zhuǎn)實(shí)體類--fastjson

    這篇文章主要介紹了java 實(shí)現(xiàn)反射 json動(dòng)態(tài)轉(zhuǎn)實(shí)體類--fastjson,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • Spring 自定義事件監(jiān)聽(tīng)器實(shí)現(xiàn)步驟詳解

    Spring 自定義事件監(jiān)聽(tīng)器實(shí)現(xiàn)步驟詳解

    本文詳細(xì)介紹了Spring自定義事件監(jiān)聽(tīng)器的實(shí)現(xiàn)步驟,包括定義事件、發(fā)布事件、監(jiān)聽(tīng)并處理事件等,結(jié)合異步和自定義線程池等擴(kuò)展能力,通過(guò)標(biāo)準(zhǔn)化步驟,提供代碼示例和關(guān)鍵說(shuō)明,幫助開(kāi)發(fā)者實(shí)現(xiàn)事件驅(qū)動(dòng)架構(gòu),感興趣的朋友跟隨小編一起看看吧
    2025-12-12
  • 兩行Javascript代碼生成UUID的方法

    兩行Javascript代碼生成UUID的方法

    這篇文章主要介紹了兩行Javascript代碼生成UUID的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • SpringBoot快速搭建web項(xiàng)目詳細(xì)步驟總結(jié)

    SpringBoot快速搭建web項(xiàng)目詳細(xì)步驟總結(jié)

    這篇文章主要介紹了SpringBoot快速搭建web項(xiàng)目詳細(xì)步驟總結(jié) ,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-12-12
  • java9遷移注意問(wèn)題總結(jié)

    java9遷移注意問(wèn)題總結(jié)

    本篇文章給大家詳細(xì)整理了java9遷移注意的問(wèn)題,希望我們整理的內(nèi)容能夠幫助到大家。
    2018-02-02
  • 解析mybatis-plus中的resultMap簡(jiǎn)單使用

    解析mybatis-plus中的resultMap簡(jiǎn)單使用

    mybatis-plus也只是聽(tīng)過(guò),可是終究沒(méi)有使用過(guò)。于是自己花幾天晚上的時(shí)間研究mybatis-plus的使用。這篇文章主要介紹了mybatis-plus的resultMap簡(jiǎn)單使用,需要的朋友可以參考下
    2021-11-11
  • SpringBoot接口參數(shù)的默認(rèn)值與必要性最佳實(shí)踐記錄

    SpringBoot接口參數(shù)的默認(rèn)值與必要性最佳實(shí)踐記錄

    這篇文章主要介紹了SpringBoot接口參數(shù)的默認(rèn)值與必要性,通過(guò)合理設(shè)置接口參數(shù)的默認(rèn)值和必要性,我們可以創(chuàng)建出既健壯又靈活的?RESTful?API,需要的朋友可以參考下
    2024-08-08
  • Springboot集成Mybatis-plus、ClickHouse實(shí)現(xiàn)增加數(shù)據(jù)、查詢數(shù)據(jù)功能

    Springboot集成Mybatis-plus、ClickHouse實(shí)現(xiàn)增加數(shù)據(jù)、查詢數(shù)據(jù)功能

    本文給大家講解Springboot + mybatis-plus 集成ClickHouse,實(shí)現(xiàn)增加數(shù)據(jù)、查詢數(shù)據(jù)功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-08-08

最新評(píng)論

临邑县| 拉孜县| 普格县| 淮北市| 通江县| 神农架林区| 漠河县| 东乌| 永康市| 永兴县| 龙泉市| 大石桥市| 亚东县| 西昌市| 得荣县| 新邵县| 五大连池市| 黄冈市| 武乡县| 吴江市| 新竹县| 湖口县| 东台市| 名山县| 兰溪市| 任丘市| 内乡县| 称多县| 利辛县| 离岛区| 会同县| 英吉沙县| 沂源县| 延长县| 岳阳市| 洛浦县| 卢湾区| 珠海市| 永善县| 吉木萨尔县| 姜堰市|