refresh和自动配置大致流程
AutoConfigurationImportSelector的getAutoConfigurationEntry获取自动配置实体(重点)
前面讲了那么多,都是为了这里啊,不然直接上来都不知道是怎么来的,我们来看看这个干了什么,别看就那么点,其实里面很复杂,简单的说就是从我们初始化加载的所有的jar
包下的META-INF/spring.factories
属性中找到org.springframework.boot.autoconfigure.EnableAutoConfiguration
属性,其实这个时候以及有缓存啦,前面初始化的时候已经全加载过了。然后进行去重,再获取要排除的名字,检查排除的类的合理性,然后排除,再进行条件类过滤,因为可能有些配置类缺少某些类就不能用了,触发自动装配导入事件,最后封装成AutoConfigurationEntry
返回。
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);//获取自动装配类
configurations = removeDuplicates(configurations);//去重
Set<String> exclusions = getExclusions(annotationMetadata, attributes);//获取要排除的
checkExcludedClasses(configurations, exclusions);//检查要排除的
configurations.removeAll(exclusions);//排除
configurations = filter(configurations, autoConfigurationMetadata);//过滤
fireAutoConfigurationImportEvents(configurations, exclusions);//触发导入事件
return new AutoConfigurationEntry(configurations, exclusions);
}
主要自动配置类都在这里,当然我们可以自定义,后面我们会自定义一个:
AutoConfigurationImportSelector的getCandidateConfigurations获取EnableAutoConfiguration类型的名字集合
这个代码我们前面很熟悉啊,就不多说了,从缓存中加载对应EnableAutoConfiguration
类型的类名字,最终加载了124
个,好多啊,没关系,后面过滤就没那么多了。
AutoConfigurationImportSelector的removeDuplicates去重
这个很巧妙,放进Set
里又拿出来放进List
里:
protected final <T> List<T> removeDuplicates(List<T> list) {
return new ArrayList<>(new LinkedHashSet<>(list));
}
AutoConfigurationImportSelector的getExclusions获取要排除的
其实就是从注解属性的exclude
和excludeName
获取,当然还有个环境配置属性spring.autoconfigure.exclude
也可以,就是说可以在yml
或者propertise
里配啦,其他就不多说了。
AutoConfigurationImportSelector的checkExcludedClasses检查要排除的
其实就是看下要排除的在不在自动配置集合里,有不在的就报异常,可能要排除的并不是自动配置的类,表示无效排除:
private void checkExcludedClasses(List<String> configurations, Set<String> exclusions) {
List<String> invalidExcludes = new ArrayList<>(exclusions.size());
for (String exclusion : exclusions) {
if (ClassUtils.isPresent(exclusion, getClass().getClassLoader()) && !configurations.contains(exclusion)) {
invalidExcludes.add(exclusion);//不在自动配置类里,还要排除的,属于无效排除,要抛异常
}
}
if (!invalidExcludes.isEmpty()) {
handleInvalidExcludes(invalidExcludes);
}
}
protected void handleInvalidExcludes(List<String> invalidExcludes) {
StringBuilder message = new StringBuilder();
for (String exclude : invalidExcludes) {
message.append("\t- ").append(exclude).append(String.format("%n"));
}
throw new IllegalStateException(String.format(
"The following classes could not be excluded because they are not auto-configuration classes:%n%s",
message));
}
AutoConfigurationImportSelector的filter过滤
这里会获取过滤器,其实就是OnClassCondition
,OnWebApplicationCondition
,OnBeanCondition
这几个条件,他会去配置类的注解上查找相应的条件类是否存在,不存在就会被过滤掉,过滤的时候可能会开启线程,帮助一起处理,因为配置类数量多。如果多核的话,会用启动一个线程去分担一半数量的检查,会判断条件类是否能加载到,不能就被过滤掉了,如果用多个线程可能效果不太好,spring
团队应该做过实验,2
个最好。
具体的细节下次说。
好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。