// @Condition条件计算器
class ConditionEvaluator {
// 计算的上下文
private final ConditionContextImpl context = new ConditionContextImpl(registry, environment, resourceLoader);
// 校验是否需要跳过,未指定分阶段处理,也就是那个阶段都需要处理,调用@Conditon接口
public boolean shouldSkip(AnnotatedTypeMetadata metadata) {
return shouldSkip(metadata, null);
}
/**
* 根据@Conditional注解决定是否跳过某项
*
* @param metadata 注解的元信息
* @param phase 调用的阶段,在指定的阶段才会调用Condition接口,如果不在当前指定的阶段,则不会调用Condition接口
* @return true:当前类需要被跳过,不会被加载
*/
public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
// 如果没有注解信息,或者不存在Conditional注解,不处理,放行
if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
return false;
}
// 如果未指定在某个阶段处理
if (phase == null) {
// 判断元数据类型是不是注解的类型,并且是配置类
// candidateIndicators.add(Component.class.getName());
// candidateIndicators.add(ComponentScan.class.getName());
// candidateIndicators.add(Import.class.getName());
// candidateIndicators.add(ImportResource.class.getName());
if (metadata instanceof AnnotationMetadata && ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
// 递归调用,传递当前阶段是处理一个配置类
return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
}
// 如果是其他类型,那处理的阶段当做是注册一个Bean来处理
return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
}
// 获取@Condition注解的处理类信息
List<Condition> conditions = new ArrayList<>();
// 获取注解上所有Condition接口实现类的全类名
for (String[] conditionClasses : getConditionClasses(metadata)) {
// 遍历所有全类名
for (String conditionClass : conditionClasses) {
// 使用类加载器加载该类,并且实例化
Condition condition = getCondition(conditionClass, this.context.getClassLoader());
// 保存处理类
conditions.add(condition);
}
}
// 对condition进行排序
AnnotationAwareOrderComparator.sort(conditions);
// 遍历所有的处理类
for (Condition condition : conditions) {
// 处理的阶段
ConfigurationPhase requiredPhase = null;
// 如果Conditionl类型是配置类ConfigurationCondition类型
// 获取ConfigurationCondition提供的自定义阶段
if (condition instanceof ConfigurationCondition) {
requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
}
// 如果不是ConfigurationCondition类型,或者ConfigurationCondition没有指定处理的阶段,再或者给定的阶段和处理的阶段一致的情况下
// 再调用Condition.matches方法,对当前类进行判断
// 1. 如果是ConfigurationCondition类型,但是它未提供阶段的值,这个时候,表示无论在那个阶段都会处理,所以直接调用condition接口进行最终判断
// 2. 如果不是ConfigurationCondition类型,那就是普通的Condition类型,这个时候也是直接调用condition接口进行最终判断
// 3. 是ConfigurationCondition类型,并且ConfigurationCondition指定要处理的阶段和实际处理的阶段一致,这个时候才会处理,所以才需要调用condition接口进行最终判断
// 4. 是ConfigurationCondition类型,但是指定的处理阶段和正在处理的阶段不一致,这个时候就没有必要处理了,也不会调用condition接口
if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
return true;
}
}
// 处理完上面这些接口,最终确定是否需要被跳过
return false;
}
/**
* 获取注解上的类
*/
private List<String[]> getConditionClasses(AnnotatedTypeMetadata metadata) {
// 找到该类上的Conditional注解信息
MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes(Conditional.class.getName(), true);
// 获取注解的value属性
Object values = (attributes != null ? attributes.get("value") : null);
// 返回类的名称集合
return (List<String[]>) (values != null ? values : Collections.emptyList());
}
private Condition getCondition(String conditionClassName, @Nullable ClassLoader classloader) {
// 使用类加载加加载该类
Class<?> conditionClass = ClassUtils.resolveClassName(conditionClassName, classloader);
// 实例化该类
return (Condition) BeanUtils.instantiateClass(conditionClass);
}
}
// 将@Bean解析成BeanDefinition的类
class ConfigurationClassBeanDefinitionReader {
// 处理@Bean方法
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
// 使用条件计算器计算当前配置类是否需要被跳过,指定当前处理的阶段是注册某个Bean的阶段
if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
// 如果需要被跳过,保存当前方法的@Bean不会被加载
configClass.skippedBeanMethods.add(methodName);
return;
}
}
// 处理配置类的Class
private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
// 使用跟踪类型的计算器,它相比普通的ConditionEvaluator类说,就是多了一个处理@Import类的校验规则,并且缓存了哪些类被忽略了
// 内部还是调用普通ConditionEvaluator的实现
if (trackedConditionEvaluator.shouldSkip(configClass) {
// 获取当前配置类是不是缓存了标记被跳过
Boolean skip = this.skipped.get(configClass);
// 如果没有被标记
if (skip == null) {
// 判断当前配置类是不是导入的
if (configClass.isImported()) {
boolean allSkipped = true;
// 获取导入当前类的所有配置类
for (ConfigurationClass importedBy : configClass.getImportedBy()) {
// 递归校验,校验导入当前类的配置类是否需要被跳过
// 意思就是有N个类导入当前类,只有所有的类的都被跳过,则当前被导入的类也要被跳过
// 因为导入当前类的所有类都不符合条件,所以当前类也没办法成为Bean
// 但是只要有一个导入的Bean是不需要被跳过,则当前配置类就有用
if (!shouldSkip(importedBy)) {
// 如果有一个不需要被跳过,标识不是所有的都需要被跳过
allSkipped = false;
break;
}
}
// 如果被导入当前类的所有配置类都被跳过了,那么当前配置类也会被跳过
if (allSkipped) {
skip = true;
}
}
// 如果上面没有标记当前类需要被跳过
// 那么再次使用Condition注解计算器计算当前配置类是否需要被跳过
if (skip == null) {
// 给定处理的阶段为注册Bean的阶段
skip = conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN);
}
// 缓存当前配置类是否需要被跳过
this.skipped.put(configClass, skip);
}
return skip;
}){
// 如果需要被跳过
// 获取Bean名称
String beanName = configClass.getBeanName();
// 如果已经保存了该bean的BeanDefinition,删除
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
// 再删除Import的关系
this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
return;
}
}
}
// 解析所有配置类信息的解析器
class ConfigurationClassParser {
// 处理整个配置类
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
// 使用条件计算器计算当前配置类是否需要被跳过,指定当前处理的阶段是解析配置类的阶段
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
}
// 处理配置类的各个阶段的Bean
protected void doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) {
// 处理配置类的ComponentScans
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
// 如果不存在注解,或者
// 使用条件计算器计算当前配置类是否需要被跳过,指定当前处理的阶段是注册Bean的阶段
if (componentScans.isEmpty() || this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
return;
}
}
}
// 包扫描器
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {
// 判断当前类是不是一个可用的Bean
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
// 使用排除的过滤器校验
for (TypeFilter tf : this.excludeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return false;
}
}
// 使用包含的过滤器校验
for (TypeFilter tf : this.includeFilters) {
// 如果包含了该类,才需要校验Condition
if (tf.match(metadataReader, getMetadataReaderFactory())) {
// 判断@Condition是否符合条件
return isConditionMatch(metadataReader);
}
}
return false;
}
// Condition条件匹配
private boolean isConditionMatch(MetadataReader metadataReader) {
// 如果没有条件计算器,创建一个
if (this.conditionEvaluator == null) {
this.conditionEvaluator = new ConditionEvaluator(getRegistry(), this.environment, this.resourcePatternResolver);
}
// 使用条件计算器校验
return !this.conditionEvaluator.shouldSkip(metadataReader.getAnnotationMetadata());
}
}
Spring中@Conditional和Condition接口的运行原理
最新推荐文章于 2024-09-10 22:48:37 发布
1440

被折叠的 条评论
为什么被折叠?



