【SpringBoot(二)】@Condition 注解

32 篇文章 15 订阅
5 篇文章 0 订阅

在springboot的自动化配置中,这个注解起到了相当重要的作用。

其一般与@Bean注解一起使用,作用就是满足一定条件才将@Bean修饰的bean注入容器。

下面看一个例子,仅仅当classpath下有某一个类才注入bean。

定义一个Condition接口的实现:
 

public class MyCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        try {
            Class<?> clazz = context.getClassLoader().loadClass("com.liyao.A");
            if (clazz != null) {
                return true;
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return false;
    }
}

会在classpath里查找“com.liyao.A”这个类,如果有就注入。

下面是配置类:

class MyBean{

}

@Configuration
public class JavaConfig {

    public static void main(String args[]) {
        ApplicationContext app = new AnnotationConfigApplicationContext(JavaConfig.class);
        MyBean myBean = (MyBean) app.getBean("myBean");
        System.out.println(myBean == null);
    }

    @Bean(name = "myBean")
    @Conditional(MyCondition.class)
    public MyBean getBean() {
        return new MyBean();
    }
}

在工程里写一个com.liyao.A的java文件,一起编译,最终会输出false。

如果没有类会抛出noBean的异常。

 

那么@Condition注解是如何被Spring框架处理的呢?

因为该注解与@Configuration一起使用,其处理过程是在处理@Configuration的BeanFactoryPostProcessor里,即ConfigurationClassPostProcessor。

在这个processor里,最终会处理@Bean注解,将bean注册,注册前会看是否有@Condition注解,会调用其match方法看是否需要注入:

	private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass,
			TrackedConditionEvaluator trackedConditionEvaluator) {

		if (trackedConditionEvaluator.shouldSkip(configClass)) {
			removeBeanDefinition(configClass);
			return;
		}

		if (configClass.isImported()) {
			registerBeanDefinitionForImportedConfigurationClass(configClass);
		}
		for (BeanMethod beanMethod : configClass.getBeanMethods()) {
			loadBeanDefinitionsForBeanMethod(beanMethod);
		}
		loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
		loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
	}

match的调用在conditionEvaluator里:

		public boolean shouldSkip(ConfigurationClass configClass) {
			Boolean skip = this.skipped.get(configClass);
			if (skip == null) {
				if (configClass.isImported()) {
					if (shouldSkip(configClass.getImportedBy())) {
						// The config that imported this one was skipped, therefore we are skipped
						skip = true;
					}
				}
				if (skip == null) {
					skip = conditionEvaluator.shouldSkip(configClass.getMetadata(),
							ConfigurationPhase.REGISTER_BEAN);
				}
				this.skipped.put(configClass, skip);
			}
			return skip;
		}

	public boolean shouldSkip(AnnotatedTypeMetadata metadata, 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);
		}

		for (String[] conditionClasses : getConditionClasses(metadata)) {
			for (String conditionClass : conditionClasses) {
				Condition condition = getCondition(conditionClass, context.getClassLoader());
				ConfigurationPhase requiredPhase = null;
				if (condition instanceof ConfigurationCondition) {
					requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
				}
				if (requiredPhase == null || requiredPhase == phase) {
					if (!condition.matches(context, metadata)) {
						return true;
					}
				}
			}
		}

		return false;
	}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值