-
什么是自动配置?自动配置原理?
- SpringBoot所谓的自动配置是基于JavaConfig技术(配置类 + 注解的方式)的,而不是XML
- SpringBoot会根据当前(环境)依赖自动应用一些JavaConfig来做配置
- SpringBoot会通过一些条件筛选判断是否需要某个配置(动态插拔)
-
原理
@SpringBootApplication public class DemoApplication { public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args); } }
@SpringBoot是一个复合注解,其中有
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited // 以上为原注解 @SpringBootConfiguration // 表明当前类是一个根配置类(级别较@Configuration高) @EnableAutoConfiguration @ComponentScan( excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class} ), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class} )} ) public @interface SpringBootApplication { ... ...}
在@EnableAutoConfiguration中
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited // 以上为原注解 @AutoConfigurationPackage // 作用是自动加载扫描包的路径(这也是为什么SpringBoot应用的启动类总是在最外层的原因) @Import({AutoConfigurationImportSelector.class}) public @interface EnableAutoConfiguration {... ...}
而@Import注解会将AutoConfigurationImportSelector.class注入到IOC容器中
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered { ... ... // 此方法实现至DeferredImportSelector接口 // 而DeferredImportSelector又继承自ImportSelector接口 public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!this.isEnabled(annotationMetadata)) { return NO_IMPORTS; } else { AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); } } ... ... }
ImportSelector接口:SpringBoot自动配置的核心
public interface ImportSelector { // 返回一个String数组,数组里的内容是一些类的路径名称,Spring会把这个数组返回的路径名称的类加载注入到IOC容器中 String[] selectImports(AnnotationMetadata var1); ... ... }
String[ ] selectImports 是如何加载类路径信息的?
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
this.getAutoConfigurationEntry(annotationMetadata)
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) { ... ... List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes); ... ... } }
this.getCandidateConfigurations(annotationMetadata, attributes)
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()); ... ... }
简而言之selectImports方法最终会找到spring.factories文件,并扫描这个文件,将里面的配置类加载到IOC容器中
实际上这些以xxxAutoConfiguration结尾的文件就是一个个的JavaConfig,它能将配置文件中配置的属性与标注着有@ConfigurationProperties的类文件中的相应的属性进行绑定。例如:server.port / spring.application.name / spring.rabbitmq.localhost等属性。