概括自动装配的原理: 前提:@SpringBootApplication 里的@ComponentScan注解(不加参数默认情况下)只能扫描当前包和子包下的class,也就是说只能把当前包和子包下的类注入到spring容器中,当外包引进来的时候,包名称基本都是自己厂商的包路径,所以这些class都不能直接放到容器中,所以需要特殊处理 @SpringBootApplication包含3个注解:1,EnableAutoConfiguration,2,SpringBootConfiguration,3,ComponentScan 基本流程:@SpringBootApplication–>@EnableAutoConfiguration–》@Import({AutoConfigurationImportSelector.class}),–》AutoConfigurationImportSelector.class AutoConfigurationImportSelector.class继承DeferredImportSelector.class–》继承ImportSelector.class–》调用selectImports()(实际不是这样调用的,但是不影响自动装配整体理解)–》返回的String[]就是spring容器里要加载的class,其实就是利用了@Import注解引入新的class到spring容器的原理,根本上还是反射 spring没有创造新的注解,只是利用配置文件通过反射+@Import将需要整合的其他组件的入口类放到spring容器中,所有厂商都遵循springboot这个配置文件的规范, 并且创建一个spring的configration配置类,通过配置类加载自己的核心组件,然后将配置类按固定的格式配置到META-INF/spring.factories里,通过maven或者其他打包工具打成jar,当导入到springboot里的时候,springboot会读取这个配置文件,然后都统一加载了。也就是所谓的约定优于配置
具体步骤:
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
//获取候选的配置信息,加载META-INF/spring.factories里所有的配置信息到内存,和spi的原理差不多
List configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
//过滤掉重复的class
configurations = this.removeDuplicates(configurations);
this.getExclusions() 去掉需要排除的class(不需要加载到容器里的class),一般用法@SpringBootApplication(exclude = RedisAutoConfiguration.class()-->排除的是配置类)
Set exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
//过滤掉没有引入jar包的class(因为很多class,需要做过滤,通过META-INF/spring-autoconfigure-metadata.properties查找加载class的条件,基于@Conditional注解)
configurations = this.getConfigurationClassFilter().filter(configurations);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
ps:springboot启动的时候并没有走到ImportSelector.class的String[] selectImports()方法
因为AutoConfigurationImportSelector.class继承DeferredImportSelector.class,需要实现getImportGroup(),返回的是泛型Group的子类,
如果返回的不是空则执行了Group的selectImports()
DeferredImportSelector.class和ImportSelector.class是@Configguration的处理时机,包括对@ImportResource、@Bean这些注解的处理,(这里只是对@Bean修饰的方法的处理,并不是立即调用@Bean修饰的方法)
不过对自动装配的整体流程来说不是很影响
|