成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

Spring Boot中的那些條件判斷

Nekron / 3177人閱讀

摘要:通過(guò)操作系統(tǒng)進(jìn)行條件判斷,從而進(jìn)行配置。分別對(duì)布爾,字符串和數(shù)字三種類(lèi)型進(jìn)行判斷。通過(guò)指定的資源文件是否存在進(jìn)行條件判斷,比如判斷來(lái)決定是否自動(dòng)裝配組件。判斷當(dāng)前環(huán)境是否是應(yīng)用。

Spring Boot中的那些Conditional

spring boot中為我們提供了豐富的Conditional來(lái)讓我們得以非常方便的在項(xiàng)目中向容器中添加Bean。本文主要是對(duì)各個(gè)注解進(jìn)行解釋并輔以代碼說(shuō)明其用途。

所有ConditionalOnXXX的注解都可以放置在class或是method上,如果方式在class上,則會(huì)決定該class中所有的@Bean注解方法是否執(zhí)行。

@Conditional

下面其他的Conditional注解均是語(yǔ)法糖,可以通過(guò)下面的方法自定義ConditionalOnXXX
Conditional注解定義如下,接收實(shí)現(xiàn)Condition接口的class數(shù)組。

public @interface Conditional {
    Class[] value();
}

而Condition接口只有一個(gè)matchs方法,返回是否匹配的結(jié)果。

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

通過(guò)操作系統(tǒng)進(jìn)行條件判斷,從而進(jìn)行Bean配置。當(dāng)Window時(shí),實(shí)例化Bill的Person對(duì)象,當(dāng)Linux時(shí),實(shí)例化Linus的Person對(duì)象。

//LinuxCondition,為方便起見(jiàn),去掉判斷代碼,直接返回true了
public class LinuxCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        return true;
    }
}
//WindowsCondition,為方便起見(jiàn),去掉判斷代碼,直接返回false了
public class WindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
        return false;
    }
}
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Person {
    private String name;
    private Integer age;
}
//配置類(lèi)
@Configuration
public class BeanConfig {

    @Bean(name = "bill")
    @Conditional({WindowsCondition.class})
    public Person person1(){
        return new Person("Bill Gates",62);
    }

    @Bean("linus")
    @Conditional({LinuxCondition.class})
    public Person person2(){
        return new Person("Linus",48);
    }
}
public class AppTest {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);

    @Test
    public void test(){
        String osName = applicationContext.getEnvironment().getProperty("os.name");
        System.out.println("當(dāng)前系統(tǒng)為:" + osName);
        Map map = applicationContext.getBeansOfType(Person.class);
        System.out.println(map);
    }
}

輸出的結(jié)果:

當(dāng)前系統(tǒng)為:Mac OS X
{linus=Person(name=Linus, age=48)}
@ConditionalOnBean & @ConditionalOnMissingBean

這兩個(gè)注解會(huì)對(duì)Bean容器中的Bean對(duì)象進(jìn)行判斷,使用的例子是配置的時(shí)候,如果發(fā)現(xiàn)如果沒(méi)有Computer實(shí)例,則實(shí)例化一個(gè)備用電腦。

@Data
@AllArgsConstructor
@ToString
public class Computer {
    private String name;
}
@Configuration
public class BeanConfig {
    @Bean(name = "notebookPC")
    public Computer computer1(){
        return new Computer("筆記本電腦");
    }

    @ConditionalOnMissingBean(Computer.class)
    @Bean("reservePC")
    public Computer computer2(){
        return new Computer("備用電腦");
    }
}
public class TestApp {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
    @Test
    public void test1(){
        Map map = applicationContext.getBeansOfType(Computer.class);
        System.out.println(map);
    }
}

修改BeanConfig,如果注釋掉第一個(gè)@Bean,會(huì)實(shí)例化備用電腦,否則就不會(huì)實(shí)例化備用電腦

@ConditionalOnClass & @ConditionalOnMissingClass

這個(gè)注解會(huì)判斷類(lèi)路徑上是否有指定的類(lèi),一開(kāi)始看到的時(shí)候比較困惑,類(lèi)路徑上如果沒(méi)有指定的class,那編譯也通過(guò)不了啊...這個(gè)主要用于集成相同功能的第三方組件時(shí)用,只要類(lèi)路徑上有該組件的類(lèi),就進(jìn)行自動(dòng)配置,比如spring boot web在自動(dòng)配置視圖組件時(shí),是用Velocity,還是Thymeleaf,或是freemaker時(shí),使用的就是這種方式。
例子是兩套盔甲A(光明套裝)和B(暗黑套裝),如果A不在則配置B。

public interface Fighter {
    void fight();
}
public class FighterA implements Fighter {
    @Override
    public void fight() {
        System.out.println("使用光明套裝");
    }
}
public class FighterB implements Fighter {
    @Override
    public void fight() {
        System.out.println("使用暗黑套裝");
    }
}

Van是武士,使用套裝進(jìn)行戰(zhàn)斗

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Van {
    private Fighter fighter;
    public void fight(){
        fighter.fight();
    }
}

VanConfigA/B實(shí)例化武士

@Configuration
@ConditionalOnClass({FighterA.class})
public class VanConfigA {
    @Primary
    @Bean
    public Van vanA(){
        return new Van(new FighterA());
    }
}
@Configuration
@ConditionalOnClass({FighterB.class})
public class VanConfigB {
    @Bean
    public Van vanB(){
        return new Van(new FighterB());
    }
}

測(cè)試類(lèi),默認(rèn)情況,如果套裝AB都在類(lèi)路徑上,兩套都會(huì)加載,A會(huì)設(shè)置為PRIMARY,如果在target class中將FightA.class刪除,則只會(huì)加載套裝B。

@SpringBootApplication
public class TestApp implements CommandLineRunner {
    @Autowired
    private Van van;
    public static void main(String[] args) {
        SpringApplication.run(TestApp.class, args);
    }
    @Override
    public void run(String... args) throws Exception {
        //do something
       van.fight();
    }
}

另外,嘗試將兩個(gè)VanConfigA/B合并,將注解ConditionalOnClass放到方法上,如果刪除一個(gè)套裝就會(huì)運(yùn)行出錯(cuò)。

@ConditionalOnExpress

依據(jù)表達(dá)式進(jìn)行條件判斷,這個(gè)作用和@ConditionalOnProperty大部分情況可以通用,表達(dá)式更靈活一點(diǎn),因?yàn)榭梢允褂肧pEL。例子中會(huì)判斷properties中test.enabled的值進(jìn)行判斷。BeanConfig分別對(duì)布爾,字符串和數(shù)字三種類(lèi)型進(jìn)行判斷。數(shù)字嘗試了很多其他的方式均不行,比如直接使用==,貌似配置的屬性都會(huì)當(dāng)成字符串來(lái)處理。

@Data
public class TestBean {
    private String name;
}
@Configuration
@ConditionalOnExpression("#{${test.enabled:true} }")
//@ConditionalOnExpression(""zz".equalsIgnoreCase("${test.name2}")")
//@ConditionalOnExpression("new Integer("${test.account}")==1")
public class BeanConfig {
    @Bean
    public TestBean testBean(){
        return new TestBean("我是美猴王");
    }
}
@SpringBootApplication
public class TestAppCommand implements CommandLineRunner {
    @Autowired
    private TestBean testBean;

    public static void main(String[] args) {
        SpringApplication.run(TestAppCommand.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        System.out.println(testBean.getName());
    }
}
@ConditionalOnProperty

適合對(duì)單個(gè)Property進(jìn)行條件判斷,而上面的@ConditionalOnExpress適合面對(duì)較為復(fù)雜的情況,比如多個(gè)property的關(guān)聯(lián)比較。這個(gè)例子也給了三種基本類(lèi)型的條件判斷,不過(guò)貌似均當(dāng)成字符串就可以...

@Data
@AllArgsConstructor
@NoArgsConstructor
public class TestBean {
    private String name;
}
@Configuration
@ConditionalOnProperty(prefix = "test", name="enabled", havingValue = "true",matchIfMissing = false)
//@ConditionalOnProperty(prefix = "test", name="account", havingValue = "1",matchIfMissing = false)
//@ConditionalOnProperty(prefix = "test", name="name1", havingValue = "zz",matchIfMissing = false)
public class BeanConfig {

    @Bean
    public TestBean testBean(){
        return new TestBean("我是美猴王");
    }
}
@SpringBootApplication
public class TestAppCommand implements CommandLineRunner {
    @Autowired
    private TestBean testBean;
    public static void main(String[] args) {
        SpringApplication.run(TestAppCommand.class, args);
    }
    @Override
    public void run(String... args) throws Exception {
        System.out.println(testBean.getName());

    }
}
@ConditionalOnJava

可以通過(guò)java的版本進(jìn)行判斷。

@Data
public class TestBean {
}
@Configuration
@ConditionalOnJava(JavaVersion.EIGHT)
public class BeanConfig {

    @Bean
    public TestBean testBean(){
        return new TestBean();
    }
}
public class TestApp {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
    @Test
    public void test(){
        Map map = context.getBeansOfType(TestBean.class);
        System.out.println(map);
    }
}
@ConditionalOnResource

通過(guò)指定的資源文件是否存在進(jìn)行條件判斷,比如判斷ehcache.properties來(lái)決定是否自動(dòng)裝配ehcache組件。

@Data
public class TestBean {
}
@Configuration
@ConditionalOnResource(resources = "classpath:application.yml")
public class BeanConfig {

    @Bean
    public TestBean testBean(){
        return new TestBean();
    }
}
public class TestApp {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);

    @Test
    public void test(){
        Map map = context.getBeansOfType(TestBean.class);
        System.out.println(map);
    }
}
@ConditionalOnSingleCandidate

這個(gè)還沒(méi)有想到應(yīng)用場(chǎng)景,條件通過(guò)的條件是:1 對(duì)應(yīng)的bean容器中只有一個(gè) 2.對(duì)應(yīng)的bean有多個(gè),但是已經(jīng)制定了PRIMARY。例子中,BeanB裝配的時(shí)候需要看BeanA的裝配情況,所以BeanBConfig要排在BeanAConfig之后.可以修改BeanAConfig,將@Primary注解去掉,或者把三個(gè)@Bean注解去掉,BeanB就不會(huì)實(shí)例化了。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class BeanA {
    private String name;
}
@Configuration
public class BeanAConfig {

    @Bean
    @Primary
    public BeanA bean1(){
        return new BeanA("bean1");
    }
    @Bean(autowireCandidate = false)
    public BeanA bean2(){
        return new BeanA("bean2");
    }
    //@Bean(autowireCandidate = false)
    public BeanA bean3(){
        return new BeanA("bean3");
    }
}
@Data
public class BeanB {
}
@Configuration
@AutoConfigureAfter(BeanAConfig.class)
@ConditionalOnSingleCandidate(BeanA.class)
public class BeanBConfig {

    @Bean
    public BeanB targetBean(){
        return new BeanB();
    }
}
public class TestApp {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanAConfig.class, BeanBConfig.class);

    @Test
    public void test(){
        Map map = context.getBeansOfType(BeanA.class);
        System.out.println(map);
        Map map2 = context.getBeansOfType(BeanB.class);
        System.out.println(map2);
    }
}
@ConditionalOnNotWebApplication & @ConditionalOnWebApplication

判斷當(dāng)前環(huán)境是否是Web應(yīng)用。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/77536.html

相關(guān)文章

  • Spring Boot [組件學(xué)習(xí)-Spring Data JPA]

    摘要:與的關(guān)系是什么是官方提出的持久化規(guī)范。它為開(kāi)發(fā)人員提供了一種對(duì)象關(guān)聯(lián)映射工具來(lái)管理應(yīng)用中的關(guān)系數(shù)據(jù)。他的出現(xiàn)主要是為了簡(jiǎn)化現(xiàn)有的持久化開(kāi)發(fā)工作和整合技術(shù),結(jié)束現(xiàn)在,,等框架各自為營(yíng)的局面。定義了在對(duì)數(shù)據(jù)庫(kù)中的對(duì)象處理查詢(xún)和事務(wù)運(yùn)行時(shí)的的。 導(dǎo)讀: 在上篇文章中對(duì)Spring MVC常用的一些注解做了簡(jiǎn)要的說(shuō)明,在這篇文章中主要對(duì)Spring Data JPA 做一個(gè)簡(jiǎn)要的說(shuō)明,并附有一...

    andong777 評(píng)論0 收藏0
  • Spring-Boot學(xué)習(xí)筆記

    摘要:學(xué)習(xí)筆記使用很容易創(chuàng)建一個(gè)獨(dú)立運(yùn)行運(yùn)行內(nèi)嵌容器準(zhǔn)生產(chǎn)級(jí)別的基于框架的項(xiàng)目,使用你可以不用或者只需要很少的配置。異常消息如果這個(gè)錯(cuò)誤是由異常引起的。錯(cuò)誤發(fā)生時(shí)請(qǐng)求的路徑。 Spring-Boot 1.5 學(xué)習(xí)筆記 使用Spring Boot很容易創(chuàng)建一個(gè)獨(dú)立運(yùn)行(運(yùn)行jar,內(nèi)嵌Servlet容器)、準(zhǔn)生產(chǎn)級(jí)別的基于Spring框架的項(xiàng)目,使用Spring Boot你可以不用或者只需要很...

    curlyCheng 評(píng)論0 收藏0
  • 《 Kotlin + Spring Boot : 下一代 Java 服務(wù)端開(kāi)發(fā) 》

    摘要:下一代服務(wù)端開(kāi)發(fā)下一代服務(wù)端開(kāi)發(fā)第部門(mén)快速開(kāi)始第章快速開(kāi)始環(huán)境準(zhǔn)備,,快速上手實(shí)現(xiàn)一個(gè)第章企業(yè)級(jí)服務(wù)開(kāi)發(fā)從到語(yǔ)言的缺點(diǎn)發(fā)展歷程的缺點(diǎn)為什么是產(chǎn)生的背景解決了哪些問(wèn)題為什么是的發(fā)展歷程容器的配置地獄是什么從到下一代企業(yè)級(jí)服務(wù)開(kāi)發(fā)在移動(dòng)開(kāi)發(fā)領(lǐng)域 《 Kotlin + Spring Boot : 下一代 Java 服務(wù)端開(kāi)發(fā) 》 Kotlin + Spring Boot : 下一代 Java...

    springDevBird 評(píng)論0 收藏0
  • 第二十八章:SpringBoot使用AutoConfiguration自定義Starter

    摘要:代碼如下所示自定義業(yè)務(wù)實(shí)現(xiàn)恒宇少年碼云消息內(nèi)容是否顯示消息內(nèi)容,我們內(nèi)的代碼比較簡(jiǎn)單,根據(jù)屬性參數(shù)進(jìn)行返回格式化后的字符串。 在我們學(xué)習(xí)SpringBoot時(shí)都已經(jīng)了解到starter是SpringBoot的核心組成部分,SpringBoot為我們提供了盡可能完善的封裝,提供了一系列的自動(dòng)化配置的starter插件,我們?cè)谑褂胹pring-boot-starter-web時(shí)只需要在po...

    fasss 評(píng)論0 收藏0
  • Spring Boot 2.0 整合 Thymeleaf 模塊引擎

    摘要:如果還在使用以前的版本,想要使用非嚴(yán)格的,需要做以下配置在中引入依賴(lài)在中配置更多屬性配置請(qǐng)參考中模塊的屬性介紹。這樣的話(huà)很好的做到了前后端分離。 本文首發(fā)于:https://y0ngb1n.github.io/a/5... 開(kāi)發(fā)環(huán)境 org.springframework.boot spring-boot-starter-parent 2.1.0.RELEASE ...

    CoreDump 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<