@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