举例(代码如下)说明@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)