@Conditional的使用

本文深入解析Spring框架中@Conditional注解的工作原理,展示如何使用条件注解控制Bean的注册,通过实例演示Man和Woman类的条件实例化过程。
@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.youkuaiyun.com/u010502101/article/details/76554564

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值