学习springboot2的第5天(2021-12-04)13-自动配置【源码分析】自动包规则原理
【springboot自动配置原理的入门】
springboot到底是怎么神不知鬼不觉地帮我们做了很多事情。只让我们关注业务逻辑的开发。带着这个问题开始学习。
【核心注解】: @SpringBootApplication 这个注解一般是在启动程序类的类体上。 其中@SpringBootApplication这个注解等同于:下面三个注解(1=3) 1、@SpringBootConfiguration 2、@ComponentScan 3、@EnableAutoConfiguration
首先将第一个注解@SpringBootConfiguration
发现注解@SpringBootConfiguration它就是一个配置的注解。 之前学习过。 代表当前这个MainApplication类也是springboot的一个配置类。
2、@ComponentScan
这个注解就是包扫描。 【这个详细知识在学习spring的视频里面有详细讲解ComponentScan 】
3、@EnableAutoConfiguration(核心注解)
这个注解很重要。 这个注解是由 1、@AutoConfigurationPackage 2、@Import({AutoConfigurationImportSelector.class}) 这两个注解合成的。
3.1、@AutoConfigurationPackage
发现注解@AutoConfigurationPackage其实就是Import 就是给容器导入组件:@Import({Registrar.class}) 这个组件就是Registrar.class 这个Registrar.class组件的作用是什么呢? 点击看Registrar类的代码:
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
}
@Override
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new PackageImports(metadata));
}
}
发现它有两个方法:
利用Registrar给容器批量注册一系列组件。
因为如果是Import一个个导入组件太麻烦。
所以:@AutoConfigurationPackage注解是利用类Registrar批量导入组件。
问:哪一系列的组件呢? 看源码: Registrar类里面的方法1的参数1: AnnotationMetadata metadata 注解的元数据信息。 这个注解就是AutoConfigurationPackage 所以第一个参数(AnnotationMetadata metadata)就是: 注解AutoConfigurationPackage的元数据信息,这个注解标在哪里?它的每一个属性值都是什么? 那注解AutoConfigurationPackage是标在哪里了呢? 关系是这样的: 所以: 注解AutoConfigurationPackage是标在EnableAutoConfiguration注解上。 而 EnableAutoConfiguration注解是标注在SpringBootApplication 而SpringBootApplication标注在com.rtl.boot.MainApplication类上面。 所以我们在debug的时候:
解释这段代码: 加入我们想看一下这段代码执行之后的结果:
new PackageImports(metadata).getPackageNames()
选中这段代码,然后右键: 得到的结果: 为什么是这个报名呢? 因为这个注解标注在这个MainApplication上。 这个类的全类名是:com.rtl.boot.MainApplication 然后把这个包名封装在数组里面。然后注册进去。 相当于这个Registrar类把某个包里面的组件全部注册进来。
总结: 注解AutoConfigurationPackage是将指定的一个包下面的组件导入进来 这个包就是Main程序所有在包(com.rtl.boot.MainApplication里面的com.rtl.boot) 这就解释了:默认的包路径是main程序所在的包。
|