说在前面
本次开始spring-boot-autoconfigure源码解析,关注“天河聊架构”查阅更多精彩源码解析文章。
源码解析
这里是springboot重要,也是经典实现部分。
上一篇文章组件扫描器扫描组件的时候会扫描到这个注解@SpringBootApplication
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration public @interface SpringBootConfiguration { }
重要解析下下面的这个注解,其他注解在spring源码解析系列文章中已介绍过。
@SuppressWarnings("deprecation") @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(EnableAutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration {
springboot的autoconfigure主要是依赖@EnableAutoConfiguration实现。当然还有其他辅助的注解,如@ConditionalOnClass这个注解,判断指定的类是否在classpath下,为什么你引入了相关的包就会把相关的环境配置初始化好是这个注解在检查你引入了哪些依赖包,如springmvc的等等。比如还有@ConditionalOnProperty注解,判断属性是否配置了指定的值,根据配置的指定值来加载相关配置,当然还有一些@Conditional*注解是在加载配置的时候做判断。这里不详细介绍了。
进入到这个方法org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#selectImports
@Override public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } try { AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader .loadMetadata(this.beanClassLoader); AnnotationAttributes attributes = getAttributes(annotationMetadata); // =》 List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); configurations = removeDuplicates(configurations); configurations = sort(configurations, autoConfigurationMetadata); // 解析排除的自动化配置 Set<String> exclusions = getExclusions(annotationMetadata, attributes); checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); // 过滤自动化配置 configurations = filter(configurations, autoConfigurationMetadata); fireAutoConfigurationImportEvents(configurations, exclusions); return configurations.toArray(new String[configurations.size()]); } catch (IOException ex) { throw new IllegalStateException(ex); } }
进入到这个方法org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getCandidateConfigurations
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { // 从META-INF/spring.factories路径下加载EnableAutoConfiguration配置的类 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; }
默认自动加载的配置在这里
# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
这里不一一介绍。
返回到这个方法org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getExclusions去除@SpringBootApplication注解上指定加载的默认配置类
protected Set<String> getExclusions(AnnotationMetadata metadata, AnnotationAttributes attributes) { Set<String> excluded = new LinkedHashSet<String>(); excluded.addAll(asList(attributes, "exclude")); excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName"))); excluded.addAll(getExcludeAutoConfigurationsProperty()); return excluded; }
进入这个方法org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getExcludeAutoConfigurationsProperty
private List<String> getExcludeAutoConfigurationsProperty() { if (getEnvironment() instanceof ConfigurableEnvironment) { // 解析application.properties配置文件中spring.autoconfigure.exclude 属性 RelaxedPropertyResolver resolver = new RelaxedPropertyResolver( this.environment, "spring.autoconfigure."); Map<String, Object> properties = resolver.getSubProperties("exclude"); if (properties.isEmpty()) { return Collections.emptyList(); } List<String> excludes = new ArrayList<String>(); for (Map.Entry<String, Object> entry : properties.entrySet()) { String name = entry.getKey(); Object value = entry.getValue(); if (name.isEmpty() || name.startsWith("[") && value != null) { excludes.addAll(new HashSet<String>(Arrays.asList(StringUtils .tokenizeToStringArray(String.valueOf(value), ",")))); } } return excludes; } RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(getEnvironment(), "spring.autoconfigure."); String[] exclude = resolver.getProperty("exclude", String[].class); return Arrays.asList((exclude != null) ? exclude : new String[0]); }
进入这个方法org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#filter
private List<String> filter(List<String> configurations, AutoConfigurationMetadata autoConfigurationMetadata) { long startTime = System.nanoTime(); String[] candidates = configurations.toArray(new String[configurations.size()]); boolean[] skip = new boolean[candidates.length]; boolean skipped = false; // 从META-INF/spring.factories路径加载AutoConfigurationImportFilter,解析 @ConditionalOnClass 判断classpath路径下有指定类, // @ConditionalOnMissingClass classpath路径下没有指定注解,进行初始化applicationContext前的校验 for (AutoConfigurationImportFilter filter : getAutoConfigurationImportFilters()) { invokeAwareMethods(filter); boolean[] match = filter.match(candidates, autoConfigurationMetadata); for (int i = 0; i < match.length; i++) { if (!match[i]) { skip[i] = true; skipped = true; } } } if (!skipped) { return configurations; } List<String> result = new ArrayList<String>(candidates.length); for (int i = 0; i < candidates.length; i++) { if (!skip[i]) { result.add(candidates[i]); } } 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 new ArrayList<String>(result); }
下面触发自动配置事件并执行监听器,自动配置加载完毕。
说在最后
本次仅代表个人观点,仅供参考。