springboot自动装配

た 入场券 2022-10-29 15:27 306阅读 0赞

从主启动类开始

  1. import org.springframework.boot.SpringApplication;
  2. import org.springframework.boot.autoconfigure.SpringBootApplication;
  3. @SpringBootApplication
  4. public class MainApplication {
  5. public static void main(String[] args) {
  6. SpringApplication.run(MainApplication.class, args);
  7. }
  8. }

上述代码,是一个springboot的web应用程序的入口类,想要了解springboot是如何装配的,我们需要了解@SpringBootApplication这个注解。

1.@SpringBootApplication

  1. @SpringBootConfiguration
  2. @EnableAutoConfiguration
  3. @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
  4. @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
  5. public @interface SpringBootApplication {

1.1.@ComponentScan

指定扫描的包路径,value是一个数组,可以同时指定多个包路径,详细说明略。

1.2.@SpringBootConfiguration

  1. @Configuration
  2. public @interface SpringBootConfiguration {

其实就是一个配置类,也就是说,入口类本身就被标识为一个配置类,没什么可说的。

1.3.@EnableAutoConfiguration

这个注解,表面意思为:开启自动配置。顾名思义,springboot的自动装配机制应该与这个注解有关。

  1. @AutoConfigurationPackage
  2. @Import(AutoConfigurationImportSelector.class)
  3. public @interface EnableAutoConfiguration {

点开这个注解我们可以看到,注解头上有含义的两行,做了两件事情:

  • @AutoConfigurationPackage:扫描并注册我们自己写的java类到spring容器
  • @Import(AutoConfigurationImportSelector.class):注册springboot提供的自动配置类到spring容器

1.3.1.@AutoConfigurationPackage

  1. @Import(AutoConfigurationPackages.Registrar.class)
  2. public @interface AutoConfigurationPackage {

可以看到,@AutoConfigurationPackage注解其实是向容器中导入了一个AutoConfigurationPackages.Registrar的实例对象,那么这个实例对象有哪些作用呢?接着看。

1.3.1.1.AutoConfigurationPackages.Registrar

  1. static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
  2. @Override
  3. public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
  4. register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
  5. }
  6. ...
  7. }

其中

  1. register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));

这个代码中,其实就是完成了我们自己写的类的扫描。
new PackageImports(metadata).getPackageNames().toArray(new String[0])获取到的是指定扫描包的路径,如果未明确指定,默认为主启动类所在的包名。
在debug模式下就可以轻松看到。
在这里插入图片描述
具体的注册细节暂时不深究。

1.3.2.@Import(AutoConfigurationImportSelector.class)

这个注解,很明显,作用是向spring容器中注入了一个AutoConfigurationImportSelector的对象。

1.3.2.3.AutoConfigurationImportSelector

这个类所做的,是将springboot提供好的自动配置装载进spring容器。
这个类中有一个方法:

  1. protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {

这个方法是获取所有的自动配置类的实体,debug看一下,实际上就是获取了springboot写好的127个自动配置类实体。
在这里插入图片描述
这127个类是在spring-boot-autoconfigure模块下定义的,如下图所示

在这里插入图片描述
spring-boot在启动时,默认就装载了这些自动配置类,但是并没有启用,只有在引入相关依赖包的时候,这些自动配置才真正被启用,这种按需加载的原理是基于条件注解实现的,如下图所示:
在这里插入图片描述
条件注解功能强大,这里不详细展开,请自行探索或参阅其它文章。

发表评论

表情:
评论列表 (有 0 条评论,306人围观)

还没有评论,来说两句吧...

相关阅读