SpringBoot自动配置原理解析
文章目录
- 前言
- SpringBoot自动配置概述
- 自动配置的核心注解
- @SpringBootApplication注解
- @EnableAutoConfiguration注解解析
- AutoConfigurationImportSelector核心实现
- selectImports方法分析
- getAutoConfigurationEntry方法详解
- getCandidateConfigurations方法
- SpringFactoriesLoader机制
- loadFactoryNames方法实现
- loadSpringFactories方法核心逻辑
- spring.factories文件格式
- 条件注解机制
- 自动配置的执行流程
- 总结
前言
SpringBoot作为Spring生态系统中的重要组成部分,其最大的特色就是约定优于配置的设计理念,而自动配置机制正是这一理念的核心体现。通过自动配置,SpringBoot能够根据项目中的依赖和配置,自动装配相应的Bean,极大地简化了传统Spring项目的配置工作。
SpringBoot自动配置概述
SpringBoot自动配置是一套智能化的配置机制,它能够根据classpath中存在的jar包、配置文件中的属性值以及其他条件,自动为应用程序配置相应的Bean。这种机制让开发者无需编写大量的XML配置文件或Java配置类,就能快速搭建一个功能完整的Spring应用。自动配置的核心思想是通过条件注解来判断是否需要创建某个Bean。只有当特定条件满足时,相应的配置类才会生效,Bean才会被创建并加入到Spring容器中。
自动配置的核心注解
@SpringBootApplication注解
SpringBoot应用的入口点通常标注有@SpringBootApplication注解,这个注解是一个复合注解,包含了三个重要的注解:
其中@EnableAutoConfiguration是自动配置的核心注解,它负责启动SpringBoot的自动配置机制。
@EnableAutoConfiguration注解解析
@EnableAutoConfiguration注解的源码如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";Class<?>[] exclude() default {};String[] excludeName() default {};
}
这个注解通过@Import导入了AutoConfigurationImportSelector类,这个类是自动配置机制的核心实现。
AutoConfigurationImportSelector核心实现
AutoConfigurationImportSelector类实现了ImportSelector接口,Spring容器会调用其selectImports方法来获取需要导入的配置类。
selectImports方法分析
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return NO_IMPORTS;}AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
这个方法首先检查自动配置是否启用,然后调用getAutoConfigurationEntry方法获取自动配置条目。
getAutoConfigurationEntry方法详解
源码如下:
protected AutoConfigurationEntry getAutoConfigurationEntry(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 = getConfigurationClassFilter().filter(configurations);fireAutoConfigurationImportEvents(configurations, exclusions);return new AutoConfigurationEntry(configurations, exclusions);
}
这个方法的执行流程包括以下几个步骤:
- 获取候选配置类列表
- 移除重复的配置类
- 获取排除的配置类
- 检查排除的配置类是否合法
- 从候选配置中移除排除的配置
- 通过过滤器进一步筛选配置类
- 触发自动配置导入事件
其实主要的就是getCandidateConfigurations和filter方法,一个是来得到配置类的List集合,另一个是用来对过滤不符合条件注解的那些配置类。
getCandidateConfigurations方法
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方法从META-INF/spring.factories
文件中加载所有的自动配置类。
SpringFactoriesLoader机制
SpringFactoriesLoader是SpringBoot中一个重要的工具类,它负责从classpath下的META-INF/spring.factories文件中加载配置信息。
loadFactoryNames方法实现
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {ClassLoader classLoaderToUse = classLoader;if (classLoaderToUse == null) {classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();}String factoryTypeName = factoryType.getName();return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}
loadSpringFactories方法核心逻辑
通过SpringFactoriesLoader来加载META-INF/spring.factories文件中的所有自动配置类,并将其缓存起来。
spring.factories文件格式
spring.factories文件采用Properties格式,其中key是接口或抽象类的全限定名,value是实现类的全限定名列表。以spring-boot-autoconfigure包中的spring.factories为例:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
...
条件注解机制
SpringBoot自动配置的智能之处在于条件注解的使用。这些注解决定了配置类在什么条件下才会生效。
自动配置的执行流程
SpringBoot自动配置的完整执行流程可以概括为以下几个阶段:
- 首先是启动阶段。当Spring容器启动时,会处理@SpringBootApplication注解,进而处理@EnableAutoConfiguration注解。
- 然后是加载阶段。AutoConfigurationImportSelector被调用,从META-INF/spring.factories文件中加载所有候选的自动配置类。
- 接下来是过滤阶段。通过各种条件注解对候选的配置类进行过滤,只保留满足条件的配置类。
- 最后是实例化阶段。Spring容器实例化通过过滤的配置类,并创建相应的Bean。
总结
SpringBoot的自动配置机制通过条件注解、SpringFactoriesLoader、META-INF/spring.factories文件等技术,实现了智能化的Bean配置。它大大简化了Spring应用的配置工作,理解自动配置的原理不仅有助于更好地使用SpringBoot,也能帮助我们在必要时创建自己的自动配置,提高开发效率。