交流
商城
MCN
登入
注册
首页
提问
分享
讨论
建议
公告
动态
发表新帖
发表新帖
第7-2 章:AutoConfigurationImportSelector
分享
未结
0
1325
李延
LV6
2021-05-22
悬赏:20积分
# 作用 springboot的自动装配。当我们导入对应jar包后,如:aop、jpa等将进行自动的初始化设置。 # 代码解析 当前类为DeferredImportSelector类,所以我们以其子类的AutoConfigurationGroup的process 和selectImports方法为入口,进行解析。 # process ```java @Override public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) { Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector, () -> String.format("Only %s implementations are supported, got %s", AutoConfigurationImportSelector.class.getSimpleName(), deferredImportSelector.getClass().getName())); //获取需要自动加载的bean路径 AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector) .getAutoConfigurationEntry(annotationMetadata); //将其保存到autoConfigurationEntries中 this.autoConfigurationEntries.add(autoConfigurationEntry); for (String importClassName : autoConfigurationEntry.getConfigurations()) { this.entries.putIfAbsent(importClassName, annotationMetadata); } } ``` 我们看到其获取自动装配的bean是通过AutoConfigurationImportSelector的getAutoConfigurationEntry来获取的,我们继续跟进getAutoConfigurationEntry方法。 ```java protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) { //判断变量spring.boot.enableautoconfiguration 表示是否开启自动装配,默认开启 if (!isEnabled(annotationMetadata)) { return EMPTY_ENTRY; } //获取属性,主要是exclude 属性,表示自动装配时忽略的bean AnnotationAttributes attributes = getAttributes(annotationMetadata); //加载所有候选集合 List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); //去重 configurations = removeDuplicates(configurations); //获取需要排除的对象 Set<String> exclusions = getExclusions(annotationMetadata, attributes); //检测排除,如果需要排除的class可以加载并且在候选集中,报错 checkExcludedClasses(configurations, exclusions); //在后后选集中去吃排除类 configurations.removeAll(exclusions); // 过滤不需要的对象 configurations = getConfigurationClassFilter().filter(configurations); // 发送自动装配事件 fireAutoConfigurationImportEvents(configurations, exclusions); // 返回结果 return new AutoConfigurationEntry(configurations, exclusions); } ``` 对于上面内容我们逐步分析。 ## getCandidateConfigurations 获取所有的后续集,代码如下: ```java protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you " + "are using a custom packaging, make sure that file is correct."); return configurations; } ``` 我们又看到了SpringFactoriesLoader.loadFactoryNames。其中我们再springboot最开始一章中已经说明, 这个是去META-INF/spring.factories文件加载指定的class路径,这里加载的是EnableAutoConfiguration。 具体如下截图:  在这里配置了很多路径,默认情况下有131个。 ## getExclusions 和 checkExcludedClasses 我们在使用 @SpringBootApplication注解时,可以指定exclude。这一步就是排除指定内容。不作解析 ## getConfigurationClassFilter().filter 上面几步中,我们加载了所有需要自动装配的候选集,但哪些是我们需要的,就在这一步执行。 ### getConfigurationClassFilter ```java private ConfigurationClassFilter getConfigurationClassFilter() { if (this.configurationClassFilter == null) { List<AutoConfigurationImportFilter> filters = getAutoConfigurationImportFilters(); for (AutoConfigurationImportFilter filter : filters) { invokeAwareMethods(filter); } this.configurationClassFilter = new ConfigurationClassFilter(this.beanClassLoader, filters); } return this.configurationClassFilter; } protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() { return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader); } ``` 我们看到AutoConfigurationImportFilter过滤器也是通过同样方法在META-INF/spring.factories中配置。  我们看到一共有 3个不同的过滤器。我们先看一下在哪些调用了这3个过滤器,再回头说明这3个过滤器作用 ### filter ```java List<String> filter(List<String> configurations) { long startTime = System.nanoTime(); String[] candidates = StringUtils.toStringArray(configurations); boolean skipped = false; for (AutoConfigurationImportFilter filter : this.filters) { boolean[] match = filter.match(candidates, this.autoConfigurationMetadata); for (int i = 0; i < match.length; i++) { if (!match[i]) { candidates[i] = null; skipped = true; } } } if (!skipped) { return configurations; } List<String> result = new ArrayList<>(candidates.length); for (String candidate : candidates) { if (candidate != null) { result.add(candidate); } } if (logger.isTraceEnabled()) { int numberFiltered = configurations.size() - result.size(); logger.trace("Filtered " + numberFiltered + " auto configuration class in " + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms"); } return result; } ``` 在上面代码中我们看到通过循环filters(也就是我们之前加载的3个过滤器)。如果有其中一个返回false就说明当前类不可以自动装配。 ## AutoConfigurationImportFilter 判断当前类是否可以自动装配,默认共3个。其实我们通过名称就可以明白各自的作用: - OnBeanCondition 当指定的bean存在时, - OnClassCondition 当指定的class存在时 - OnWebApplicationCondition 当OnWebApplicationCondition存在时
回帖
消灭零回复
提交回复
热议榜
java 相关知识分享
8
好的程序员与不好的程序员
6
写给工程师的十条精进原则
5
spring boot以jar包运行配置的logback日志文件没生成
5
一步一步分析SpringBoot启动源码(一)
5
MockMvc测试
5
【吐槽向】是不是有个吐槽的板块比较好玩
4
logstash jdbc同步mysql多表数据到elasticsearch
3
IntelliJ IDEA 优质License Server
3
.gitignore忽略规则
3
SpringBoot启动源码分析
3
一步一步分析SpringBoot启动源码(三)
3
2
一步一步分析SpringBoot启动源码(二)
2
积分不够将无法发表新帖
2
官方产品
Meta-Boot - 基于MCN
MCN - 快速构建SpringBoot应用
微信扫码关注公众号