目录

1.@SpringBootApplication

2.@ComponentScan

3.@EnableAutoConfiguration

     3.1 @AutoConfigurationPackage

     3.2 @Import(AutoConfigurationImportSelector.class)

4.总结


1.@SpringBootApplication

       来看一下自动装配的起点:@SpringBootApplication

SpringBoot自动装配(版本2.4.4)_springboot

       点进去看下@SpringBootApplication源码:

SpringBoot自动装配(版本2.4.4)_springboot_02

       三个Java元注解:@Target、@Retention、@Documented。

       @Inherited:如果一个类用上了@Inherited修饰的注解,那么其子类也会继承这个注解。具体可以查看这篇博文:javascript:void(0)

       @SpringBootConfiguration:三个Java元注解:@Target、@Retention、@Documented,加上一个Spring的@Configuration

SpringBoot自动装配(版本2.4.4)_springboot_03

       由此我们可以知道@SpringBootApplication等同于@Configuration、@ComponentScan、@EnableAutoConfiguration

2.@ComponentScan

       SpringBoot默认配置了两个自定义的过滤器TypeExcludeFilter和AutoConfigurationExcludeFilter

SpringBoot自动装配(版本2.4.4)_原理_04

       TypeExcludeFilter作用:提供TypeFilters从中加载BeanFactory并自动应用于SpringBootApplication扫描的排除项。等同于:

@ComponentScan(excludeFilters = @Filter(类型= FilterType.CUSTOM,类= TypeExcludeFilter.class))

       AutoConfigurationExcludeFilter:自动配置扫描过滤器。作用:如果扫描到一个类配置了@Configuration并且该类也配置了@EnableAutoConfiguration内自动装配的216个注解其中之一,那么将其过滤掉。(说白了就是如果该类上打了216个自动装项的注解,那么就将该类装配进Spring容器。具体这216个自动装配注解哪里来的,本文下面会解释)

SpringBoot自动装配(版本2.4.4)_原理_05

SpringBoot自动装配(版本2.4.4)_原理_06

SpringBoot自动装配(版本2.4.4)_springboot_07

SpringBoot自动装配(版本2.4.4)_springboot_08

3.@EnableAutoConfiguration

       点进源码和上面一样,具体功能由@AutoConfigurationPackage和@Import(AutoConfigurationImportSelector.class)两个注解实现。

SpringBoot自动装配(版本2.4.4)_源码_09

     3.1 @AutoConfigurationPackage

       可以看到@AutoConfigurationPackage具体功能由@Import(AutoConfigurationPackages.Registrar.class)实现。

SpringBoot自动装配(版本2.4.4)_原理_10

       @Import注解是由 Spring 提供的,作用是将某个类实例化并加入到 Spring IoC 容器中。所以我们要想知道@Import注解究竟实现了什么功能就需要了解Registrar这个类里包含了哪些方法。

SpringBoot自动装配(版本2.4.4)_自动装配_11

       determineImportsf方法在项目运行的时候并没有触发断电,查阅官方文档解释如下:

SpringBoot自动装配(版本2.4.4)_自动装配_12

       而registerBeanDefinitions方法,触发断点后发现new PackageImport(metadata).getPackageName()方法返回的就是@SpringBootApplication注解所在的类的包名。所以@AutoConfigurationPackage注解的作用是扫描与@SpringBootApplication标注的类同一包下的所有组件。

     3.2 @Import(AutoConfigurationImportSelector.class)

SpringBoot自动装配(版本2.4.4)_自动装配_13

       这个类着重看selectImports方法,由getAutoConfigurationEntry方法获取自动配置条目。

SpringBoot自动装配(版本2.4.4)_springboot_14

       然后我们再进入到这个叫做getCandidateConfigurations的方法中,这个方法名告诉我们这个方法的作用是获取候选配置。

SpringBoot自动装配(版本2.4.4)_源码_15

       从断言处我们已经可以发现一些端疑了,发现springboot去"META-INF/spring.factories"路径下寻找自动装配类。继续跟进SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass()方法,再跟进loadSpringFactories(classLoaderToUse)

SpringBoot自动装配(版本2.4.4)_spring_16

SpringBoot自动装配(版本2.4.4)_自动装配_17

        终于看到了自动装配路径:"FACTORIES_RESOURCE_LOCATION"

SpringBoot自动装配(版本2.4.4)_自动装配_18

       接下来的逻辑就很清晰了,包META-INF下获取spring.factories配置文件,读取配置并返回自动装配列表。

SpringBoot自动装配(版本2.4.4)_原理_19

      通过断点调试,笔者发现Springboot会从spring-boot.jar、spring-breans.jar、spring-boot-autoconfiguration三个包下的"META-INF/spring.factories"读取默认配置。同时我们也可以设想,将第三方starter加入springboot自动装配也是相同的道理,只要将自己的XXautoconfiguration类写到自己包"META-INF"路径下spring.factories文件中即可。

4.总结

  1. Spring Boot 在启动时除了扫描与启动类同一包下的组件之外,还会检查各个 jar 包中是否存在 META-INF/spring.factories 文件,为自动装配做准备。
  2. 第三方的 spring-boot-starter 会通过将自己的自动装配类写到 META-INF/spring.factories 中让Spring Boot加载到容器中,使自动装配类能够生效。