@Conditional
:Spring4.0 介紹了一個新的註解@Conditional,它的邏輯語義能夠做爲"If…then…else…"來對bean的註冊起做用。java
Conditional 是由 SpringFramework 提供的一個註解,位於 org.springframework.context.annotation 包內,定義以下。spring
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) public @interface Conditional { Class<? extends Condition>[] value(); }
SpringBoot 模塊大量的使用@Conditional 註釋,咱們能夠將Spring的@Conditional註解用於如下場景:數組
咱們須要一個類實現Spring提供的Condition接口,它會匹配@Conditional所符合的方法,而後咱們可使用咱們在@Conditional註解中定義的類來檢查。ide
public interface Condition { boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata); }
先來看一個簡單一些的示例,咱們假設有三個角色老師Teacher、學生Student和父母Parent,三種環境Linux、Windows和MacOSX,若是是Linux環境,就註冊Teacher,若是是Windows環境就註冊Parent,若是是Mac 環境就註冊Student。代碼示例以下:測試
//若是當前工程運行在Windows系統下,就註冊Student public class Student {} //若是當前工程運行在Linux系統下,就註冊Teacher public class Teacher {} // 若是是Mac OSX 系統,就註冊Parent public class Parent {}
public class LinuxCondition implements Condition { public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // 獲取系統環境的屬性 String systemName = context.getEnvironment().getProperty("os.name"); if(systemName.contains("Linux")){ return true; } return false; } } //自定義一個判斷條件 public class WindowsCondition implements Condition { /* * ConditionContext context: spring容器上下文環境 * AnnotatedTypeMetadata metadata :@Conditional修飾類型信息 */ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { String systemName = context.getEnvironment().getProperty("os.name"); if(systemName.contains("Windows")){ return true; } return false; } } public class OsxCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { String property = context.getEnvironment().getProperty("os.name"); if(property.equals("Mac OS X")){ return true; } return false; } }
@Configuration public class AppConfig { @Conditional(OsxCondition.class) @Bean public Student student(){ return new Student(); } @Conditional(LinuxCondition.class) @Bean public Teacher teacher(){ return new Teacher(); } @Conditional(WindowsCondition.class) @Bean public Parent parent(){ return new Parent(); } }
public class ConditionTest { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); String[] names = context.getBeanDefinitionNames(); for(String name : names){ System.out.println("name = " + name); } } }
由輸出能夠看出,name = student 被輸出到控制檯,也就是說,我當前所用的系統環境是MacOSX環境,因此註冊的是OSXCondition,也就是student的bean。.net
也能夠進行手動修改vm.options,把當前的系統環境變爲Linux 或者Windows,以Idea爲例:code
在Edit Configurations
中找到vm.options 選項,把系統環境改成 Linux,以下:對象
而後從新啓動測試,發現Teacher 被注入進來了,修改當前環境爲Windows,觀察Parent也被注入進來並輸出了。blog
@Conditional 註解能夠做用在類上,表示此類下面全部的bean知足條件後均可以進行注入,一般與@Configuration註解一塊兒使用。接口
AppClassConfig
,在類上標註@Conditional()註解,並配置相關bean,以下:@Conditional(value = OsxCondition.class)
上文表示若是是OsxCondition.class 的話,就註冊student、teacher、parent
由於@Conditional註解的value 方法默認傳遞一個數組,因此能夠接受多個condition,爲了測試以下狀況,
新建一個 TestCondition
類,以下:
// 單純爲了測試 public class TestCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // 返回false,表示不匹配 return false; } }
修改一下AppClassConfig
@Conditional(value = {OsxCondition.class,TestCondition.class})
也就是給@Conditional 多加了一個參數 TestCondition.class
啓動以前的測試類,發現上述的bean都沒有注入,也就是說,只有在知足OsxCondition.class 和 TestCondition.class 都爲true的狀況下,纔會注入對應的bean,修改TestCondition.class的matches方法的返回值爲true
,從新觀察返回結果,發現上述bean都被注入了。
@Spring3.0 也有一些和@Conditional 類似的註解,它們是Spring SPEL 表達式和Spring Profiles 註解 Spring4.0的@Conditional 註解要比@Profile 註解更加高級。@Profile 註解用來加載應用程序的環境。@Profile註解僅限於根據預約義屬性編寫條件檢查。 @Conditional註釋則沒有此限制。
Spring中的@Profile 和 @Conditional 註解用來檢查"If…then…else"的語義。然而,Spring4 @Conditional是@Profile 註解的更通用法。
文章參考:
https://blog.csdn.net/xcy1193068639/article/details/81491071