先从启动配置注解 SpringbootApplication来看,点开查看。 最上面的四个是元注解。 主要是下面的三个注解。
第一个:@SpringBootConfiguration, 点进去查看,
可以看到,主要是一个Configuration 注解,标识这个类是配置类。
第三个(第二个在下面看):@ComponentScan
指定组件扫描的路径,指定扫描哪些组件。
第二个是核心 ,@EnableAutoConfiguration
点击进入查看也有两个核心注解: 1,第一个:@AutoConfigurationPackage, 点进去查看。有一个@Import注解导入了一个Registter。 这里实际上使用Register 导入了一堆组件,并不是只导入了这一个组件,进入Register, 会调用这里的方法。
至于为什么这个可以看Import 注解的作用,高级用法。
这里第一个方法的参数是一个注解的元信息, 这个注解是谁?我们从AutoConfigurationPackage跳过来的,这个注解就是这个。 而注解的元信息表示注解标在了哪个类上,其属性值是什么。 在该方法上加个断点debug: 这个注解标注的类在启动类MainApplication上,因为@SpringBootApplication是一个合成注解,包含这个AutoConfigurationPackage。所以从debug信息中可以看到MainApplication,如下: 然后这个方法干了啥呢?
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages
.PackageImports(metadata))
.getPackageNames()
.toArray(new String[0]));
}
先new 了一个对象,拿到元信息metadata,然后获取的报名,即这一段代码:new AutoConfigurationPackages .PackageImports(metadata)) .getPackageNames() 这一段拿到了启动类所在的包路径:如下: 最后一个.toArray(new String[0])); 将所有该包下组件都放入到一个数组中了(这里就不要理解为转成一个数组了,放到一个数组最好了)。 然后通过AutoConfigurationPackages.register,注册进去。 这就解释了为什么用Springboot时,默认的包路径?是启动类所在的包。。。
2,然后看@EnableAutoConfiguration 的第二个注解了@Import({AutoConfigurationImportSelector.class}) ,这个使用了AutoConfigurationImportSelector 类。进入这个类里面查看 这个selectImports 指定要导入哪些,都放到String数组返回,根据这个数组来确定。 所以核心都落在了this.getAutoConfigurationEntry 这个方法上了。 跳到这个方法,打一个断点debug:
拿到configurations 大小有127个。这是拿到127个组件,这些是默认导入到容器中的组件。 单步进入:进入这个方法查看:使用的SpringFactoriesLoader 加载 在进入这个loadFactoryNames 方法
再进入这个loadSpringFactories方法:最后返回的是一个map list集合。
初始时上面方法的result 必定是空的,所以会优先执行else 的语句块 这里会加载当前工程下所有包,包括导入的包MET-INF 下的spring.factories。 有些jar包就没有这个spring.factories 但是springboot的包下就存在这个springboot.factories 但是前面的127个组件,实际上是autoconfigration 包下的spring.factories所指定的自动配置类。 但是这127个没有全部放入到springboot的容器中,有些是生效的有些是没有生效的。这127个默认场景的是 ** 默认全部加载,但是最终会按需配置。 ** 这些配置是根据标在它上面的@Conditional相关注解判断是否生效。 例如:下面的aop 配置,只有Advice 类存在这个配置类才会生效。 其他的autoconfigure类也相同。
总结:
@SpringBootConfiguration :指定了当前类是一个配置类 。 @ComponentScan : 指定扫描的包路径。 @EnableAutoConfiguration 的@AutoConfigurationPackage 确定了启动类所在的包。 @EnableAutoConfiguration 的@Import({AutoConfigurationImportSelector.class}) :确定了要加载的所有场景的自动配置类,并根据application.properties文件按需进行配置。
|