12、常见Conditional注解源码解析-ConditionalOnClass

举例(代码如下)说明@ConditionalOnClass注解的作用:

在 classpath 下加载 DruidDataSource.class(classpath下有对应的jar包) , 加载成功则DruidDataSourceAutoConfigure 可以被注册进Spring容器中。

@ConditionalOnClass(DruidDataSource.class)
...
public class DruidDataSourceAutoConfigure {
	...
}

下面我们来看看源码:

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

	Class<?>[] value() default {};

	/**
	 * The classes names that must be present.
	 * @return the class names that must be present.
	 */
	String[] name() default {};

}
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
		AnnotatedTypeMetadata metadata) {
	ClassLoader classLoader = context.getClassLoader();
	ConditionMessage matchMessage = ConditionMessage.empty();
	// 1-处理ConditionalOnClass注解
	// 从标注@ConditionalOnClass注解的类Bean1OnClass的metadata
	// 获取的@ConditionalOnClass的value的全类名: com...onclass.StubClass 
	List<String> onClasses = getCandidates(metadata, ConditionalOnClass.class);
	if (onClasses != null) {
		// 判断classpath下是否"不存在"onClasses 中的类,不存在的类放入List<String>中返回
		List<String> missing = getMatches(onClasses, MatchType.MISSING, classLoader);
		if (!missing.isEmpty()) {
			// 有不存在的类,则noMatch,表示匹配失败
			return ConditionOutcome
					.noMatch(ConditionMessage.forCondition(ConditionalOnClass.class)
							.didNotFind("required class", "required classes")
							.items(Style.QUOTE, missing));
		}
		// 都存在情况下,填入一些信息进对象 matchMessage 中
		matchMessage = matchMessage.andCondition(ConditionalOnClass.class)
				.found("required class", "required classes").items(Style.QUOTE,
						getMatches(onClasses, MatchType.PRESENT, classLoader));
	}
	// 2-处理ConditionalOnMissingClass注解
	List<String> onMissingClasses = getCandidates(metadata,
			ConditionalOnMissingClass.class);
	if (onMissingClasses != null) {
		List<String> present = getMatches(onMissingClasses, MatchType.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,
						getMatches(onMissingClasses, MatchType.MISSING, classLoader));
	}
	return ConditionOutcome.match(matchMessage);
}
getMatches:181, OnClassCondition (o.s.boot.autoconfigure.condition)
getMatchOutcome:127, OnClassCondition (o.s.boot.autoconfigure.condition)
matches:47, SpringBootCondition (o.s.boot.autoconfigure.condition)
shouldSkip:102, ConditionEvaluator (o.s.context.annotation) [2]
shouldSkip:81, ConditionEvaluator (o.s.context.annotation) [1]
shouldSkip:64, ConditionEvaluator (o.s.context.annotation)
isConditionMatch:371, ClassPathScanningCandidateComponentProvider (o.s.context.annotation)
isCandidateComponent:355, ClassPathScanningCandidateComponentProvider (o.s.context.annotation)
findCandidateComponents:288, ClassPathScanningCandidateComponentProvider (o.s.context.annotation)
doScan:272, ClassPathBeanDefinitionScanner (o.s.context.annotation)
parse:135, ComponentScanAnnotationParser (o.s.context.annotation)
doProcessConfigurationClass:287, ConfigurationClassParser (o.s.context.annotation)
processConfigurationClass:245, ConfigurationClassParser (o.s.context.annotation)
parse:198, ConfigurationClassParser (o.s.context.annotation)
parse:167, ConfigurationClassParser (o.s.context.annotation)
processConfigBeanDefinitions:308, ConfigurationClassPostProcessor (o.s.context.annotation)
postProcessBeanDefinitionRegistry:228, ConfigurationClassPostProcessor (o.s.context.annotation)
invokeBeanDefinitionRegistryPostProcessors:272, PostProcessorRegistrationDelegate (o.s.context.support)
invokeBeanFactoryPostProcessors:92, PostProcessorRegistrationDelegate (o.s.context.support)
invokeBeanFactoryPostProcessors:687, AbstractApplicationContext (o.s.context.support)
refresh:525, AbstractApplicationContext (o.s.context.support)
refresh:122, EmbeddedWebApplicationContext (o.s.boot.context.embedded)
refresh:693, SpringApplication (o.s.boot)
refreshContext:360, SpringApplication (o.s.boot)
run:303, SpringApplication (o.s.boot)
run:1118, SpringApplication (o.s.boot)
run:1107, SpringApplication (o.s.boot)
main:18, HelloSpringBootApplication (com.yh.stu.springboot)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring Boot中,@Conditional注解和@AutoConfigureAfter注解是非常常用的注解,下面我来给你详细解析一下这两个注解。 ## @Conditional注解 @Conditional注解Spring Boot中非常重要的一个注解,在Spring Boot中,很多自动配置都是通过@Conditional注解来实现的。 @Conditional注解可以根据满足某些条件来决定是否创建一个bean。比如,我们可以根据某个类是否存在来决定是否创建一个bean,具体示例如下: ```java @Configuration @Conditional(ExistClassCondition.class) public class MyConfiguration { @Bean public MyBean myBean() { return new MyBean(); } } public class ExistClassCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { try { Class.forName("com.example.MyClass"); return true; } catch (ClassNotFoundException e) { return false; } } } ``` 上面的代码中,我们定义了一个MyConfiguration类,并且在该类上加了@Conditional注解,该注解的参数是一个Condition的实现类ExistClassCondition。ExistClassCondition类中的matches方法返回true的条件是com.example.MyClass类存在。 这样,当com.example.MyClass类存在的时候,MyBean这个bean才会被创建。否则,MyBean这个bean不会被创建。 ## @AutoConfigureAfter注解 @AutoConfigureAfter注解也是Spring Boot中比较常用的注解之一,它可以用来控制自动配置的顺序。 比如,我们可以通过@AutoConfigureAfter注解来控制某个自动配置类在另一个自动配置类之后加载,具体示例如下: ```java @Configuration @AutoConfigureAfter(MyAutoConfiguration.class) public class MyAnotherAutoConfiguration { // ... } ``` 上面的代码中,我们定义了一个MyAnotherAutoConfiguration类,并且在该类上加了@AutoConfigureAfter注解,该注解的参数是MyAutoConfiguration.class。这样,在Spring Boot启动时,MyAutoConfiguration这个自动配置类会先于MyAnotherAutoConfiguration这个自动配置类被加载。 总结:@Conditional注解和@AutoConfigureAfter注解都是Spring Boot中非常实用的注解。通过@Conditional注解可以实现根据满足某些条件来决定是否创建一个bean,通过@AutoConfigureAfter注解可以控制自动配置类的加载顺序,这些都是我们在实际开发中非常常用的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java硕哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值