SpringBoot自动装配原理
项目层级:
从启动类SpringbootCrmApplication开始看:
-
@SpringBootApplication:(springboot的应用)启动类必贴.
-
点进@SpringBootApplication注解:
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication{ }
主要看这三条注解:
@SpringBootConfiguration //声明当前类为配置类,每个项目有且只有一个
@EnableAutoConfiguration //开启自动配置
@ComponentScan //扫描贴了注解的类和文件并返回bean对象交由spring管理
重点是第二条注解@EnableAutoConfiguration,点进注解查看
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {}
@Import({AutoConfigurationImportSelector.class}):导入配置类
进入AutoConfigurationImportSelector.class(自动配置选择器),找到getCandidateConfigurations(获取候选配置)方法,会拿到一个候选配置集合configurations (后续会提到)
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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;
}
进入loadFactoryNames(获取工厂名称)方法
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
进入loadSpringFactories方法
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
classLoader.getResources(FACTORIES_RESOURCE_LOCATION)
}
类加载器加载文件 常量名称:FACTORIES_RESOURCE_LOCATION
点击常量名称,就可以看到是获取META-INF/spring.factories文件的内容
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
路径是META-INF/spring.factories,那我们从jar包中查找
自动配置为一个Map集合,=号左边为key,右边为value,切割Map拿到一个集合configurations,成为当前项目的候选配置
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
候选配置为什么会生效?
拿WebMvcAutoConfiguration举例子(在Auto Configura找到点击进入))
同时满足三个注解条件才生效,三个条件任何一个不满足都不会生效:
- 例如第一个条件:满足是一个web项目,并且是一个servlet应用
@ConditionalOnWebApplication(type = Type.SERVLET)
- 第二个条件:有当前依赖的字节码文件
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
- 第三个条件:以当前项目缺少bean为条件,也就是自己没有创建这个bean,没有就用默认的bean
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
其它注解解读:
自动配置是有顺序的,先配置注解内的类,再配置WebMvcAutoConfiguration
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
那为什么可以配置DispatcherServletAutoConfiguration呢?
返回一个bean对象交由spring管理,name是取的别名,无关紧要
-总结-
第一个注解:声明当前类为启动类的核心配置类
第二个注解:
- 开启自动配置
- 导入了一个自动装配的选择器
- 获取候选配置的方法,
- 从jar包获取候选配置
- 根据自动配置的条件决定是否启用自动配置