Spring - 關於條件註解的一些理解
阿新 • • 發佈:2021-08-09
目錄
- End -
﹀
﹀
﹀
夢想是鹹魚
關注一下吧
以上為本篇文章的主要內容,希望大家多提意見,如果喜歡記得點個推薦哦
作者:夢想是鹹魚
出處:https://www.cnblogs.com/maggieq8324/
本文版權歸作者和部落格園共有,歡迎轉載,轉載時保留原作者和文章地址即可。
前言
@Conditional是Spring4提供的註解,它可以根據條件判斷是否將Bean註冊到容器中,原始碼如下:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
Class<? extends Condition>[] value();
}
簡單示例
舉一個簡單的例子,如何根據當前作業系統來進行物件例項化
- 介面
public interface SystemInter { String get(); }
- 實現類
public class Linux implements SystemInter {
@Override
public String get() {
return "System's Linux";
}
}
public class Windows implements SystemInter {
@Override
public String get() {
return "System's windows";
}
}
- 控制器
public class TestController { @Autowired private SystemInter systemInter; @GetMapping(value = "/system") public String getSystem(){ return systemInter.get(); } }
上述程式碼用於表示作業系統的兩個物件,問題來了,如何根據作業系統進行相應的物件例項化,在控制器中注入呢?
這裡就可以用到@Conditional註解,通過實現Condition介面重寫方法來自定義match規則,Condition介面需要實現matches方法,返回true則注入bean,false則不注入。
- 條件類
import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; public class LinuxCondition implements Condition { @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { // 獲取配置檔案中system.condition的屬性 String name = conditionContext.getEnvironment().getProperty("system.condition"); return "linux".equalsIgnoreCase(name); } } public class WindowsCondition implements Condition { @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { // 獲取配置檔案中system.condition的屬性 String name = conditionContext.getEnvironment().getProperty("system.condition"); return "windows".equalsIgnoreCase(name); } }
- application.properties的配置,配置作業系統為windows
system.condition = windows
- 建立SystemConfiguration 類,用於配置兩個例項的注入
@Configuration
public class SystemConfiguration {
@Bean
@Conditional(LinuxCondition.class)
public SystemInter linux() {
return new Linux();
}
@Bean
@Conditional(WindowsCondition.class)
public SystemInter windows() {
return new Windows();
}
}
-
由上述程式碼可以看出,我們給兩個作業系統物件分別建立的對應的條件類,並通過配置檔案中的system.condition屬性來判斷是否例項化。
-
訪問介面結果如下,可以看出,我們從配置檔案讀取作業系統型別並例項化了windows物件。
- 切換application.properties的作業系統配置為linux
system.condition = linux
- 訪問結果如下:
- 這是個簡單的例子,卻體現了Spring的策略模式(根據環境或者條件的不同選擇不同的演算法或者策略來完成該功能)
- 注:以上的示例將@Conditional標註在方法上,而@Conditional標註在類上可以判斷該配置類中的所有Bean是否注入。
內建的條件註解
註解 | 條件 |
---|---|
@ConditionalOnBean | 當SpringIoC容器記憶體在指定Bean的條件 |
@ConditionalOnMissingBean | 當SpringIoC容器內不存在指定Bean的條件 |
@ConditionalOnClass | 當SpringIoC容器記憶體在指定Class的條件 |
@ConditionalOnMissingClass | 當SpringIoC容器內不存在指定Class的條件 |
@ConditionalOnProperty | 指定的屬性是否有指定的值 |
@ConditionalOnResource | 類路徑是否有指定的值 |
@ConditionalOnWebApplication | 當前專案是Web專案的條件 |
@ConditionalOnNotWebApplication | 當專案不是Web專案的條件 |
@ConditionalOnExpression | 基於SpEL表示式作為判斷條件 |
@ConditionalOnJava | 基於JVM版本作為判斷條件 |
@ConditionalOnJndi | 在JNDI存在時查詢指定的位置 |
@ConditionalOnSingleCandidate | 當指定Bean在SpringIoC容器內只有一個,或者雖然有多個但是指定首選的Bean |