上文我們講解了@Import的方式進行導入,本文我們將學習@Conditional xxx相關注解
主要有:
@Conditional // 根據條件判斷滿足時,則實例化當前Bean
@ConditionalOnBean // 當給定的在bean存在時,則實例化當前Bean
@ConditionalOnMissingBean // 當給定的在bean不存在時,則實例化當前Bean
@ConditionalOnClass // 當給定的類名在類路徑上存在,則實例化當前Bean
@ConditionalOnMissingClass // 當給定的類名在類路徑上不存在,則實例化當前Bean
一.@Conditional
public @interface Conditional {
Class<? extends Condition>[] value();
}
根據源碼我們使用此註解時,value的時需要繼承Condition接口
假設:
bule這個Bean存在我們就實例化SuperMan
bule01這個Bean存在我們就實例化Man
這時我們就可以採用 @Conditional進行管理
1.1 定義相關類
@Data
public class SuperMan {
private String name;
private Integer age;
}
---------
@Data
public class Man {
private String userName;
private String email;
}
--------
@Data
public class Bule {
private Integer code;
}
1.2 定義配置文件
1.2.1 定義Bean實例化文件
@Configuration
public class MainConfig {
@Bean(value = "bule01")
public Bule bule(){
return new Bule();
}
@Bean
@Conditional(value = SueperManCondition.class)
public SuperMan superMan(){
return new SuperMan("Javayh",27);
}
@Bean
@Conditional(value = ManCondition.class)
public Man man(){
return new Man("Javayh","[email protected]");
}
}
1.2.2 定義Bean實例化條件
public class ManCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata annotatedTypeMetadata) {
//獲取到bean定義的註冊類
BeanDefinitionRegistry registry = context.getRegistry();
//可以判斷容器中的bean註冊情況,也可以給容器中註冊bean
boolean definition = registry.containsBeanDefinition("bule01");
if(definition){
return true;
}
return false;
}
}
--------
public class SueperManCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata annotatedTypeMetadata) {
//獲取到bean定義的註冊類
BeanDefinitionRegistry registry = context.getRegistry();
//可以判斷容器中的bean註冊情況,也可以給容器中註冊bean
boolean definition = registry.containsBeanDefinition("bule");
if(definition){
return true;
}
return false;
}
}
1.2.3 驗證
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(MainConfig.class);
@Test
public void testCondtion(){
printBeans(applicationContext);
Bule bule = applicationContext.getBean(Bule.class);
System.out.println(bule);
SuperMan bean = applicationContext.getBean(SuperMan.class);
System.out.println(bean);
Man man = applicationContext.getBean(Man.class);
System.out.println(man);
}
private void printBeans(AnnotationConfigApplicationContext applicationContext){
String[] definitionNames = applicationContext.getBeanDefinitionNames();
for (String name : definitionNames) {
System.out.println(name);
}
}
運行之後我們發現,實例化bule01存在,這是根據條件將實例化man 這個Bean,而無法實例化 SuperMan
二.@ConditionalOnBean
源碼可以看出,也用到了 @Conditional
@Conditional({OnBeanCondition.class})
public @interface ConditionalOnBean {
//指定 條件的 Bean.Class
Class<?>[] value() default {};
//作爲條件的類的Name,Class.getName()
String[] type() default {};
//條件所需的註解類
Class<? extends Annotation>[] annotation() default {};
//容器中bean的名字
String[] name() default {};
//搜索容器層級,當前容器,父容器
SearchStrategy search() default SearchStrategy.ALL;
//可能在其泛型參數中包含指定bean類型的其他類
Class<?>[] parameterizedContainer() default {};
}
2.1 定義Bean
接下來我們修改上面的方放,當Bule作爲SuperMan的變量
@Data
@AllArgsConstructor
public class SuperMan {
private String name;
private Integer age;
private Bule bule;
}
2.2 定義Bean實例化規則
這是我們需要根據Bule是否在容器內,來進行SuperMan的實例化,做到Bule存在則SuperMan存在,否則不存在
@Configuration
public class MainConfig {
@Bean(value = "bule")
public Bule bule(){
return new Bule();
}
@Bean
@ConditionalOnBean(value = Bule.class)
public SuperMan superMan(Bule bule){
bule.setCode(123);
return new SuperMan("Javayh",27,bule);
}
@Bean
@Conditional(value = ManCondition.class)
public Man man(){
return new Man("Javayh","[email protected]");
}
}
2.3 測試
@Test
public void testCondtionOnBean(){
printBeans(applicationContext);
SuperMan bean = applicationContext.getBean(SuperMan.class);
System.out.println(bean);
}
Bule存在容器中,SuperMan被實例化
這時我們可以將Bule的實例化註釋掉,在進行測試,時容器內並沒有Bule,而SuperMan也沒 被實例化,我們書getBean就會錯
@ConditionalOnMissingBean 其實與@ConditionalOnBean正好相反,這裏就不做測試了
三.@ConditionalOnClass
public @interface ConditionalOnClass {
//指定 條件的 Bean.Class
Class<?>[] value() default {};
//條件bean的名稱
String[] name() default {};
}
其實不難發現 ConditionalOnClass 和 ConditionalOnBean 左右是一樣的,這是我們將 ConditionalOnBean 的例子改一下
@Bean
@ConditionalOnClass(value = Bule.class)
public SuperMan superMan(Bule bule){
bule.setCode(123);
return new SuperMan("Javayh",27,bule);
}
結果是一樣
擴展
@ConditionalOnExpression(當表達式爲true的時候,纔會實例化一個Bean)
@ConditionalOnNotWebApplication(不是web應用)
本文的分享暫時就到這裏,希望對您有所幫助
關注 Java有貨領取更多資料
聯繫小編。微信:372787553,帶您進羣互相學習
左側小編微信,右側獲取免費資料
- SpringCloud 自定義封裝架構https://github.com/Dylan-haiji/javayh-platform
- Java 設計模式學習代碼 https://github.com/Dylan-haiji/design-pattern
- SpringCloud學習代碼: https://github.com/Dylan-haiji/javayh-cloud
- AlibabaCloud學習代碼:https://github.com/Dylan-haiji/javayh-cloud-nacos
- SpringBoot+Mybatis 多數據源切換:https://github.com/Dylan-haiji/javayh-boot-data-soure
- Redis、Mongo、Rabbitmq、Kafka學習代碼: https://github.com/Dylan-haiji/javayh-middleware
- SpringBoot+SpringSecurity實現自定義登錄學習代碼:https://github.com/Dylan-haiji/javayh-distribution