概述
使用springboog的时候引入starter就自动为我们加载,例如我们引入 spring-boot-starter-web 之后,就自动引入了 Spring MVC 相关的 jar 包,从而自动配置 Spring MVC 。
自动装配原理
@SpringBootApplication
@SpringBootApplication: Spring Boot应用标注在某个类上说明这个类是SpringBoot的主配置类,
@SpringBootConfiguration:Spring Boot的配置类; 标注在某个类上,表示这是一个Spring Boot的配置类;
@EnableAutoConfiguration:开启自动配置功能;
@ComponentScan : 扫描包 相当于在spring.xml 配置中context:comonent-scan 但是并没有指定basepackage,如果没有 指定spring底层会自动扫描当前配置类所有在的包
@EnableAutoConfiguration
其中@Import({AutoConfigurationImportSelector.class})是重点
通过@import向spring容器注入AutoConfigurationImportSelector类
EnableAutoConfigurationImportSelector 实现了DeferredImportSelectorSpring内部在解析@Import注解时会调
用getAutoConfigurationEntry方法
getAutoConfigurationEntry方法会调用getCandidateConfigurations方法
// AutoConfigurationImportSelector.java
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
// <1> 加载指定类型 EnableAutoConfiguration 对应的,在 `META-INF/spring.factories` 里的类名的数组
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;
}
<1> 处,调用 #getSpringFactoriesLoaderFactoryClass() 方法,获得要从 META-INF/spring.factories 加载的指定类型为 EnableAutoConfiguration 类。代码如下:
// AutoConfigurationImportSelector.java
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
<1> 处,调用 SpringFactoriesLoader#loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) 方法,加载指定类型 EnableAutoConfiguration 对应的,在 META-INF/spring.factories 里的类名的数组
现在已经知道了自动装配是怎么加载的,那么问题来了,springboot自动装配调用入口在哪里?
这一块属于spring的知识点,提一嘴,使用@import注入的类spring会加载到ioc容器中,然后调用当前导入类的process方法
我们导入的类实现了
我们看下process方法
@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()));
AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
.getAutoConfigurationEntry(annotationMetadata);
this.autoConfigurationEntries.add(autoConfigurationEntry);
for (String importClassName : autoConfigurationEntry.getConfigurations()) {
this.entries.putIfAbsent(importClassName, annotationMetadata);
}
}
最终在process方法里边会加载spring.factories文件的自动配置类