spring boot 擴展了spring 的@Conditional注解呜袁,提供了很多常用的注解韩肝,例如@ConditionalOnProperty根據(jù)屬性來判斷是否要激活這個配置文件或者是激活這個Bean陪每,@ConditionalOnBean根據(jù)容器中是否有這個Bean來判斷逻澳,
@ConditionalOnClass根據(jù)項目路徑中是否有某個Class來判斷垒在,等等吧蒜魄,但是官方提供的有時不能完全滿足我們的需求,就需要我們自己來進行擴展场躯。例如我們設想一個場景:不同的環(huán)境不同的配置谈为,有個配置我們希望只在開發(fā)環(huán)境與測試環(huán)境存在,生產(chǎn)環(huán)境不存在踢关,硬編碼太low了伞鲫,我們可以試用下spring提供的Conditional,通過描述签舞,是根據(jù)描述環(huán)境的屬性來判斷這個Bean是否創(chuàng)建秕脓,可以聯(lián)想到是@ConditionalOnProperty,但是這個注解有個havingValue只接受一個值儒搭,不能接受兩個值(dev和test),這個時候我們就需要擴展這個注解吠架。下面我們開始吧,pom相對于上一節(jié)沒啥特別的變化搂鲫,就不說了傍药,我們就從代碼開始。
首先聲明一個注解
package com.shuqi.anno;
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 com.shuqi.MyOnPropertyCondition;
import org.springframework.context.annotation.Conditional;
import org.springframework.core.env.Environment;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional(MyOnPropertyCondition.class)
public @interface MyConditionalOnProperty {
String value();
String prefix() default "";
String[] name() default {};
String havingValue() default "";
boolean matchIfMissing() default false;
boolean relaxedNames() default true;
//TODO ADD ONE PROPERTY
String[] havingValues() default {};
}
沒啥太多的不同魂仍,只不過多了一個屬性havingValues是一個字符串數(shù)組類型的拐辽。下面我們看下,通過這個注解引入的Condition的判斷邏輯類MyOnPropertyCondition
package com.shuqi;
import com.shuqi.anno.MyConditionalOnProperty;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import java.util.Map;
/**
* @author olifer
*/
public class MyOnPropertyCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(MyConditionalOnProperty.class.getName());
String propertyName = (String) annotationAttributes.get("value");
String[] values = (String[]) annotationAttributes.get("havingValues");
String propertyValue = context.getEnvironment().getProperty(propertyName);
for (String havingValue : values) {
if (propertyValue.equalsIgnoreCase(havingValue)) {
return true;
}
}
return false;
}
}
里面的邏輯也很簡單擦酌,從注解中拿到value和havingValues的值俱诸,將value的內(nèi)容作為key從環(huán)境中獲取到對應的value與havingValues中的內(nèi)容進行對比,如果匹配上仑氛,返回true乙埃,那么標示這個條件通過闸英。看下我們的配置文件中的內(nèi)容
env: test
最后看下我們的配置類中的使用方式:
package com.shuqi;
import com.shuqi.anno.MyConditionalOnProperty;
import com.shuqi.model.Person;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author linyang on 18/5/1.
*/
@Slf4j
@Configuration
public class MyConfig {
@Bean
@MyConditionalOnProperty(value = "env",havingValues = {"dev","test"})
public Person person(){
log.info("創(chuàng)建Bean");
return new Person();
}
}
表達的含義是介袜,獲取env這個屬性的值與test和dev進行判斷甫何,如果包含的話,這個名字叫做person的Bean就會創(chuàng)建遇伞,否則不會創(chuàng)建辙喂。
今天就說到這里,大家可以拉取源碼看看效果鸠珠。