@Conditional 是spirng 4.0引入的註解,可以放在類和方法上 ,標示符合條件的類,spring容器纔會對其實例化
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
/**
* All {@link Condition}s that must {@linkplain Condition#matches match}
* in order for the component to be registered.
*/
Class<? extends Condition>[] value();
}
實現代碼:在spring實例化時會調用 org.springframework.context.annotation.ConditionEvaluator類的shouldSkip方法,代碼:
/**
* Determine if an item should be skipped based on {@code @Conditional} annotations.
* @param metadata the meta data
* @param phase the phase of the call
* @return if the item should be skipped
*/
public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
return false;
}
if (phase == null) {
if (metadata instanceof AnnotationMetadata &&
ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
}
return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
}
List<Condition> conditions = new ArrayList<>();
for (String[] conditionClasses : getConditionClasses(metadata)) {
for (String conditionClass : conditionClasses) {
Condition condition = getCondition(conditionClass, this.context.getClassLoader());
conditions.add(condition);
}
}
AnnotationAwareOrderComparator.sort(conditions);
for (Condition condition : conditions) {
ConfigurationPhase requiredPhase = null;
if (condition instanceof ConfigurationCondition) {
requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
}
//這個地方 去調用重寫的matches方法,如果重寫matches方法返回false時,直接跳過配置的註解語義
if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
return true;
}
}
return false;
}
==============================================分隔線==========================================
直接上代碼
Person下有兩個子類 Man和Woman
public interface Person {
public String birth();
}
public class Man implements Person {
@Override
public String birth() {
return ("This is man");
}
}
public class Woman implements Person {
@Override
public String birth() {
return("This is woman");
}
}
分別爲Man和Woman添加條件類
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class ManCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return false;//返回false
}
}
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class WomanCondition implements Condition {
/**
* 返回true 纔會被Spring實例化
* @param context
* @param metadata
* @return
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return true;
}
}
添加配置類
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ConditionConfig {
@Bean("man")
@Conditional(ManCondition.class)
public Man getMan(){
return new Man();
}
/**
* 只有 WomanCondition 中 matches方法返回true 纔會啓用配置
* @return
*/
@Bean("woMan")
@Conditional(WomanCondition.class)
public Woman getWoMan(){
return new Woman();
}
}
main方法
public class ConditionDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConditionConfig.class);
context.getBeansOfType(Person.class).forEach((beanName,bean)->{
System.err.println("Bean Name:"+beanName+" ->"+bean);
});
}
}
//響應日記
.......略
17:26:36.085 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
17:26:36.127 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source
17:26:36.129 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'woMan'
Bean Name:woMan ->condition.Woman@3427b02d
可以看到,Spring容器Person接口只會實例化一個子類 condition.Woman@3427b02d
參考文章https://blog.csdn.net/u010502101/article/details/76554564