[springboot源码分析]-Conditional

本文详细介绍了Spring框架中的`@Conditional`注解及其使用,包括`ProfileCondition`,`Java8Condition`等自定义条件,以及`@ConditionalOnClass`在自动配置中的应用,展示了条件注解如何决定Bean是否加载。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://www.baeldung.com/spring-conditional-annotations

Condition元数据

1 org.springframework.context.annotation.Conditional

1.1@Conditional定义

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
	Class<? extends Condition>[] value();
}

2 org.springframework.context.annotation.Condition

2.1 Condition接口定义

@FunctionalInterface
public interface Condition {
	boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}

2.2 Condition类图

在这里插入图片描述

2.2.1 ProfileCondition
class ProfileCondition implements Condition {

	@Override
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
		if (attrs != null) {
			for (Object value : attrs.get("value")) {
				if (context.getEnvironment().acceptsProfiles(Profiles.of((String[]) value))) {
					return true;
				}
			}
			return false;
		}
		return true;
	}
}
2.2.2 自定义Condition
class Java8Condition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return JavaVersion.getJavaVersion().equals(JavaVersion.EIGHT);
    }
}


3.SpringBootCondition

3.1. SpringBootCondition类图

在这里插入图片描述

3.1.1 OnBeanCondition 执行图-- 粗

在这里插入图片描述

3.1.2 自定义SpringBootCondition
class Java8OrJava9 extends AnyNestedCondition {
    
    Java8OrJava9() {
        super(ConfigurationPhase.REGISTER_BEAN);
    }
    
    @Conditional(Java8Condition.class)
    static class Java8 { }
    
    @Conditional(Java9Condition.class)
    static class Java9 { }

}

3.2 org.springframework.boot.autoconfigure.condition.ConditonOnXXX

在这里插入图片描述



4. @ConditionalOnClass(SomeService.class)执行之旅

  @AutoConfiguration
  public class MyAutoConfiguration {
 
  	@Configuration(proxyBeanMethods = false)
  	@ConditionalOnClass(SomeService.class)
  	public static class SomeServiceConfiguration {
  	}
  }

4.1 注解元数据

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class)
public @interface ConditionalOnClass {
	Class<?>[] value() default {};
	String[] name() default {};
}

ConditionalOnBean.name=userService

4.2 执行逻辑线路

springApplication.run(args)
--prepareContext()
----load(context,sources)
------createBeanDefinitionLoader(context,sources):: return BeanDefinitionLoader // 1

//1
BeanDefinitionLoader.load()
--AnnotatedBeanDefinitionReader.register(source) //2

//2
AnnotatedBeanDefinitionReader.register(source)
--registerBean()
----doRegisterBean()
-----abd = new AnnotatedGenericBeanDefinition(beanClass);//3
-----ConditionEvaluator.conditionEvaluator.shouldSkip(abd.getMetadata())//4

//4.ConditionEvaluator.shouldSkip()

4.2.1 ConditionEvaluator.shouldSkip()

class ConditionEvaluator {
	public boolean shouldSkip(AnnotatedTypeMetadata metadata) {
		return shouldSkip(metadata, null);
	}

	public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
		//判断是否存在Conditional类型注解
		if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
			return false;
		}

		//若phase 为空,则根据metadata类型设置phase --- 略..
		List<Condition> conditions = new ArrayList<>();
		//1. 获取所有的 conditionClasses
		for (String[] conditionClasses : getConditionClasses(metadata)) { 
			for (String conditionClass : conditionClasses) {
				//2 BeanUtils.instantiateClass(conditionClass); 实例化所有的condition
				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();
			}

			//3. condition.matches:: OnClassCondition.mathes
			if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
				return true;
			}
		}

		return false;
	}

	//1
	private List<String[]> getConditionClasses(AnnotatedTypeMetadata metadata) {
		MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes(Conditional.class.getName(), true);
		Object values = (attributes != null ? attributes.get("value") : null); //OnClassCondition.class
		return (List<String[]>) (values != null ? values : Collections.emptyList());
	}
}

4.2.2 OnClassCondition.matches()



public abstract class SpringBootCondition implements Condition {

	@Override
	public final boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		String classOrMethodName = getClassOrMethodName(metadata);  //SomeServiceConfiguration
		ConditionOutcome outcome = getMatchOutcome(context, metadata); //子类实现;;1
		logOutcome(classOrMethodName, outcome);
		recordEvaluation(context, classOrMethodName, outcome);
		return outcome.isMatch();
	}


}


//1
class OnClassCondition extends FilteringSpringBootCondition {
	
	@Override
	public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
		ClassLoader classLoader = context.getClassLoader();
		ConditionMessage matchMessage = ConditionMessage.empty();
		List<String> onClasses = getCandidates(metadata, ConditionalOnClass.class); //1.1 SomeService.class

		@ConditionalOnClass处理逻辑
		if (onClasses != null) {
			List<String> missing = filter(onClasses, ClassNameFilter.MISSING, classLoader);
			//如果存在missing; 则noMatch
			if (!missing.isEmpty()) {
				return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnClass.class)
					.didNotFind("required class", "required classes")
					.items(Style.QUOTE, missing));
			}

			//否则 返回found
			matchMessage = matchMessage.andCondition(ConditionalOnClass.class)
				.found("required class", "required classes")
				.items(Style.QUOTE, filter(onClasses, ClassNameFilter.PRESENT, classLoader));
		}

		//@ConditionalOnMissingClass 处理逻辑
		List<String> onMissingClasses = getCandidates(metadata, ConditionalOnMissingClass.class);
		if (onMissingClasses != null) {
			List<String> present = filter(onMissingClasses, ClassNameFilter.PRESENT, classLoader);
			if (!present.isEmpty()) {
				return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnMissingClass.class)
					.found("unwanted class", "unwanted classes")
					.items(Style.QUOTE, present));
			}
			matchMessage = matchMessage.andCondition(ConditionalOnMissingClass.class)
				.didNotFind("unwanted class", "unwanted classes")
				.items(Style.QUOTE, filter(onMissingClasses, ClassNameFilter.MISSING, classLoader));
		}
		return ConditionOutcome.match(matchMessage); //返回
	}

	//1.1
	private List<String> getCandidates(AnnotatedTypeMetadata metadata, Class<?> annotationType) {
		MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes(annotationType.getName(), true);
		if (attributes == null) {
			return null;
		}
		List<String> candidates = new ArrayList<>();
		addAll(candidates, attributes.get("value"));
		addAll(candidates, attributes.get("name"));
		return candidates;
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值