springboot源码解析(六)@ConditionalOnClass

在springboot中,有@ConditionalOnClass,@ConditionalOnBean,@ConditionalOnMissingClass,@ConditionalOnMissingBean等注解,这些注解的含义是有某个类或者没有某个bean才会加载,那么源码是在什么地方处理的呢,下面我们一起看下。

一、举例

我们以类EncryptionBootstrapConfiguration为例,它上面有注解:@ConditionalOnClass({ TextEncryptor.class })。

处理是在ConfigurationClassParser类的processConfigurationClass()方法中:

	protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
		if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
			return;
		}

这个方法就是查看是否有满足条件的class或者bean。shoudSkip方法就是判断是否要跳过。这个方法前面都是获取注解的元数据,核心方法是在下面这段:

		for (Condition condition : conditions) {
			ConfigurationPhase requiredPhase = null;
			if (condition instanceof ConfigurationCondition) {
				requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
			}
			if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
				return true;
			}
		}

这段中首先判断condition是否是ConfigurationCondition类型,这个获取的condition实例的类型是从@ContionalOnClass注解上获取

@Conditional(OnClassCondition.class)
public @interface ConditionalOnClass {
@Conditional(OnBeanCondition.class)
public @interface ConditionalOnBean {

只有OnBeanCondition是ConfigurationCondition类型的,所以只有在@ConditionalOnBean和@ConditionalOnMissingBean的时候requiredPhase才有值,而这个requiredPhase==phase的判断的作用,只是看过滤的时机,是在创建Configuration类的时候过滤还是在创建bean的时候过滤而已。

所以对于所有的注解来说后面的condition.matches(this.context, metadata)方法,都是必走的

	@Override
	public final boolean matches(ConditionContext context,
			AnnotatedTypeMetadata metadata) {
		String classOrMethodName = getClassOrMethodName(metadata);
		try {
			ConditionOutcome outcome = getMatchOutcome(context, metadata);
			logOutcome(classOrMethodName, outcome);
			recordEvaluation(context, classOrMethodName, outcome);
			return outcome.isMatch();
		}

第一行的getMatchOutcome方法就是通过获取对应的OnBeanCondition或者OnClassCondition获取相应的ConditionOutcome类,然后执行isMathc()方法来判断是否跳过。

有一篇相关博客介绍的不错推荐给大家:https://www.jianshu.com/p/c4df7be75d6e

你可能感兴趣的:(spring,boot源码,SpringBoot源码)