Bootstrap

SpringBoot源码学习系列——自动配置原理(三)

通过前面的文章,我们学习了SpringBoot的自动配置实现过程,其中涉及到条件注解。本文对条件注解进行介绍。
自动配置实现原理可见下列文章:
SpringBoot源码学习系列——自动配置原理(一)
SpringBoot源码学习系列——自动配置原理(二)

@Conditional条件注解

@Conditional注解介绍

@Conditional及其衍生注解用于某个类后,可以根据注解属性值指定的条件来决定是否进行Bean的实例化操作。

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {

	/**
	 * All Conditions that must match
	 * in order for the component to be registered.
	 */
	Class<? extends Condition>[] value();

}

可以看出,@Conditional的属性为Condition类型的数组,当数组中所有Condition#match方法返回true时,被注解的类才可以进行实例化。

@FunctionalInterface
public interface Condition {
    // 参数context:该接口方法用于获取Spring应用上下文信息
    // 参数metadata:该接口方法用于检查带有@Bean注解的类上是否存在其他类型注解,获取各注解的属性信息
	boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);

}

Condition接口介绍

@Conditional条件注解包含很多衍生注解,此处以@ConditionalOnWebApplication为例介绍,可以看到,@ConditionalOnWebApplication使用了@Conditional注解,并且指定条件OnWebApplicationCondition.class
在这里插入图片描述
OnWebApplicationCondition.class类继承如下,继承自FilteringSpringBootConditionFilteringSpringBootCondition又继承自SpringBootCondition且实现了AutoConfigurationImportFilterBeanFactoryAwareBeanClassLoaderAware接口,SpringBootCondition继承自Condition接口,则肯定实现了matches方法
在这里插入图片描述
下面看下SpringBootCondition抽象类:
在这里插入图片描述
核心功能通过getMatchOutcome方法实现,该方法是SpringBootCondition抽象类的一个抽象方法,交由子类实现。
下面以OnWebApplicationCondition.class为例,介绍getMatchOutcome方法:

	@Override
	public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
	    // 是否包含ConditionalOnWebApplication注解
		boolean required = metadata.isAnnotated(ConditionalOnWebApplication.class.getName());
		// 是否是web应用
		ConditionOutcome outcome = isWebApplication(context, metadata, required);
		// 使用了ConditionalOnWebApplication注解且不是web应用,则不匹配
		if (required && !outcome.isMatch()) {
			return ConditionOutcome.noMatch(outcome.getConditionMessage());
		}
		// 未使用ConditionalOnWebApplication注解且是web应用,则不匹配
		if (!required && outcome.isMatch()) {
			return ConditionOutcome.noMatch(outcome.getConditionMessage());
		}
		// 其它情况则匹配
		return ConditionOutcome.match(outcome.getConditionMessage());
	}
;