上篇博客我們詳細(xì)的聊了《JavaEE開發(fā)之Spring中的多線程編程以及任務(wù)定時(shí)器詳解》,本篇博客我們就來聊聊條件注解@Conditional以及組合條件。條件注解說簡單點(diǎn)就是根據(jù)特定的條件來選擇Bean對象的創(chuàng)建。條件注解就是可以根據(jù)不同的條件來做出不同的事情。在Spring中條件注解可以說是設(shè)計(jì)模式中狀態(tài)模式的一種體現(xiàn)方式,同時(shí)也是面向?qū)ο缶幊讨卸鄳B(tài)的應(yīng)用部分。而組合注解就是將現(xiàn)有的注解進(jìn)行組合。下方會(huì)給出具體的介紹和實(shí)例。

 

一、條件注解----@Conditional

本篇博客的本部分我們來聊一下條件注解,顧名思義,條件注解就是可以根據(jù)不同的條件來做出不同的事情。在Spring中條件注解可以說是設(shè)計(jì)模式中狀態(tài)模式的一種體現(xiàn)方式,同時(shí)也是面向?qū)ο缶幊讨卸鄳B(tài)的應(yīng)用部分。

Spring框架中,當(dāng)我們使用條件注解時(shí),我們會(huì)為每種獨(dú)立的條件創(chuàng)建一個(gè)類,根據(jù)這個(gè)類對應(yīng)的條件的成立情況我們來選擇不同的任務(wù)來執(zhí)行。當(dāng)然我們在聲明任務(wù)時(shí),一般使用接口來聲明。因?yàn)槲覀儠?huì)在Spring的配置類中指定具體條件下的具體類。接下來,我們將來看一下Spring框架中@Conditional注解的具體使用方式。

當(dāng)然同一個(gè)Service接口所對應(yīng)的條件集合中是互斥的,也就是說在特定情況下只有一個(gè)條件成立。

 

1、創(chuàng)建服務(wù)接口以及具體的服務(wù)類

首先我們來創(chuàng)建一個(gè)Service的接口,然后再基于遵循該接口的情況下來創(chuàng)建兩個(gè)Service類。下方我們將會(huì)在配置類中指定不同條件下會(huì)對應(yīng)不同的Service對象。首先我們先來創(chuàng)建Service的接口。下方這段代碼就是我們創(chuàng)建的Service的接口,該接口比較簡單,只有一個(gè)描述方法。在具體是Service類中我們將會(huì)給出description()方法的具體實(shí)現(xiàn),用此方法來區(qū)分不同類的實(shí)現(xiàn)。

package com.zeluli.conditional;public interface ConditinalServiceInteface {    public String description();
}

 

創(chuàng)建完ServiceInterface后,我們就該創(chuàng)建具體的類了。下方的FirstConditionServiceSecondConditionService兩個(gè)類都實(shí)現(xiàn)了ConditinalServiceInteface接口,并且給出了description()方法的具體實(shí)現(xiàn)。稍后,我們將會(huì)在下方類配置Bean時(shí),給出相應(yīng)的條件。本小節(jié)只是準(zhǔn)備部分。

萬碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

package com.zeluli.conditional;public class FirstConditionService implements ConditinalServiceInteface {    public String description() {        return "第一個(gè)條件成立的Service";
    }
}=========================================package com.zeluli.conditional;public class SecondConditionService implements ConditinalServiceInteface {    public String description() {        return "第二個(gè)條件成立的Service";
    }
}

萬碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

 

2、創(chuàng)建@Conditional對應(yīng)的條件類

創(chuàng)建完Service接口以及Service類后,接下來我們就來創(chuàng)建@Conditional注解所需的條件類。每個(gè)條件類對應(yīng)著一種獨(dú)立的情況,在Spring中的條件類需要實(shí)現(xiàn)Condition接口。下方是我們創(chuàng)建的兩個(gè)條件類。

這兩個(gè)條件類都實(shí)現(xiàn)了Spring框架中的Condition,并且給出了matches()方法的實(shí)現(xiàn)。matches()方法的返回值是一個(gè)布爾類型的值,如果返回false說明該條件類所對應(yīng)的條件不成立,如果返回true則說明該條件對應(yīng)的條件成立。為了簡化操作,我們就指定FirstConditional對應(yīng)的條件為false,而SecondConditional對應(yīng)的條件為true。具體的條件類的實(shí)現(xiàn)如下所示。

萬碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

package com.zeluli.conditional;import org.springframework.context.annotation.Condition;import org.springframework.context.annotation.ConditionContext;import org.springframework.core.type.AnnotatedTypeMetadata;public class FirstConditional implements Condition {    //提供條件的方法
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {        return false;
    }
}==========================================package com.zeluli.conditional;import org.springframework.context.annotation.Condition;import org.springframework.context.annotation.ConditionContext;import org.springframework.core.type.AnnotatedTypeMetadata;public class SecondConditional implements Condition {    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {        return true;
    }
}

萬碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

 

3.在Java配置類中進(jìn)行條件配置

Service的接口、Service的類以及相應(yīng)的條件創(chuàng)建完畢后,接下來我們就該在Java的配置類中將條件類與Service類對象進(jìn)行關(guān)聯(lián)了。下方代碼段就是該部分對應(yīng)的配置類。在聲明FirstConditionService類的Bean時(shí),我們使用@Conditional注解,@Conditional的參數(shù)為FirstConditional.class,也就是說明當(dāng)FirstConditional類所對應(yīng)的條件成立時(shí)FirstConditionService的對象才會(huì)被實(shí)例化。

同理,下方的SecondConditionService對應(yīng)的條件是SecondConditional。具體代碼如下所示。

萬碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

package com.zeluli.conditional;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Conditional;import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.zeluli.conditional")public class ConditionalConfig {
    
    @Bean
    @Conditional(FirstConditional.class) //指定條件類
    public FirstConditionService getFirstConditionalService() {        return new FirstConditionService();
    }
    
    @Bean
    @Conditional(SecondConditional.class)    public SecondConditionService getSecondConditionService() {        return new SecondConditionService();
    }
}

萬碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

 

4、創(chuàng)建Main方法進(jìn)行測試

接下來又到了測試的時(shí)刻了,下方我們從上面的ConditionalConfig配置類中獲取上下文,然后從上下文中獲取相應(yīng)的Service對象。在獲取對象時(shí),我們使用的是ConditionalServiceInterface接口來獲取和聲明的Bean。也就是說service變量所承載的對象是實(shí)現(xiàn)ConditionalServiceInterface接口的所有類中的某個(gè)類的對象。當(dāng)某個(gè)Service類所對應(yīng)的條件成立時(shí),該類的對象就會(huì)被創(chuàng)建。

上面我們也提到過,ConditionalServiceInterface接口下每個(gè)類對應(yīng)的這些條件必須是互斥的,也就是這些條件在特定情況下只有一個(gè)是成立的。因?yàn)槲覀優(yōu)榈诙€(gè)條件返回的是true, 所以該條件是成立的,那么SecondConditionalService類的對象就會(huì)被調(diào)用。所以我們調(diào)用service的description()方法時(shí),調(diào)用的是SecondConditionalService類中的相應(yīng)的方法。具體如下所示。

 

  萬碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

 

 

二、組合注解

組合注解這個(gè)就比較好理解了,就是將多個(gè)注解組合到一塊生成一個(gè)新的注解。使用這個(gè)新的注解就相當(dāng)于使用了該組合注解中所有的注解。這個(gè)特性還是蠻有用的,接下來我們就來看一下如何創(chuàng)建和使用組合注解。

 

1.組合注解的創(chuàng)建

接下來我們就通過一個(gè)簡單的實(shí)例來看一下如何將多個(gè)注解組合到一塊。在之前的Spring配置類中,我們經(jīng)常使用到@Configuration@ComponentScan這兩個(gè)注解,接下來,我們將其進(jìn)行組合封裝,從而形成一個(gè)新的注解。

下方這個(gè)CombinationConfiguration注解就是我們組合的新的注解,該注解中使用了@Configuration和@ComponentScan進(jìn)行修飾,也就說明@CombinationConfiguration注解兼有@Configuration和@ComponentScan這兩個(gè)注解的功能。

萬碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

package com.zeluli.combination.annotation;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@ComponentScanpublic @interface CombinationConfiguration {
    String[] value() default{};
}

萬碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

 

2.組合注解的使用

創(chuàng)建完相應(yīng)的組合注解后就到了使用的時(shí)候了,上面注解的使用和一般的注解沒有什么區(qū)別。只是這個(gè)注解表示之前寫的@Configuration和@ComponentScan這兩個(gè)注解。下方代碼截圖就是該組合注解的使用方式。

  萬碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)