Spring Boot自动配置讲解

在我们使用springboot的时候,肯定会引入一个starter的jar包,只有引入该jar包,才能引入@SpringBootApplication的注解。

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

该注解所在的包如下:
Spring Boot自动配置讲解_第1张图片
并且可以发现和该注解在同一个包下的其他注解基本上都是有关自动注入的,所以可以初步推出该注解是自动注入的灵魂。
Spring Boot自动配置讲解_第2张图片
该注解的作用是自动扫描并将众多需要的bean放到spring的IOC容器中,减少了开发人员的工作任务。现在点进去该注解,可以看到里面有三个核心注解来完成@SpringBootApplication注解的工作:@SpringBootConfiguration,@EnableAutoConfiguration
@ComponentScan
Spring Boot自动配置讲解_第3张图片
下面来逐一分析,这三个注解都起到了哪些作用。

@SpringBootConfiguration

该注解也是一个合成注解,再次点进去可以看到,里面是存在@Configuration注解的,该注解的作用是声明当前类为一个配置类,并且该类会被spring容器所管理,如下代码进行测试:

@SpringBootApplication
public class SpringbootApplicationTest {
    public static void main(String[] args) {
        //run 就是ioc容器
        ConfigurableApplicationContext run = SpringApplication.run(SpringbootApplicationTest.class, args);
        SpringbootApplicationTest bean = run.getBean(SpringbootApplicationTest.class);
        System.out.println(bean);
}

打印结果如下:
在这里插入图片描述
所以该注解声明该启动类得被IOC容器管理。

@ComponentScan

该注解的意思是当SpringBoot启动的时候,会扫描@ComponentScan注解里的包路径。该路径内所有的类只要被@Component修饰的话,就会创建该类的对象然后放到IOC容器中。该注解里面的excludeFilters会过滤一些内容,表示这些内容不会被spring扫描到,不被扫描的是手写的过滤器。
但是我们平时使用@ComponentScan注解里面需要有value值,表示是我要扫描的包路径,但是这里没有,这是为什么?
我们点进去@ComponentScan注解,查看官方说明:
Spring Boot自动配置讲解_第4张图片
也就是没有声明包路径的话,默认的就是启动类所在的包路径。

@EnableAutoConfiguration

该注解是SpringBoot自动配置的灵魂,我们点进去看一下它的描述:Spring Boot自动配置讲解_第5张图片
它会自动帮我们注入我们标记的类或者猜测我们想要注入的类,并且说明了该注解的扫描最好是当前以及子目录。我们再看一下它由哪些注解组成:
在这里插入图片描述

@Import(AutoConfigurationImportSelector.class)

前述

该注解也是进行了直接导入bean,它导入的bean类型是AutoConfigurationImportSelector,中文翻译过来也就是自动配置类导入的意思。我们从Springboot启动来一点一点的分析,看看该类到底起了一个什么作用:
1、在启动类的run方法上打上断点:
Spring Boot自动配置讲解_第6张图片
2、点进run方法里面,之后点击进入SpringApplication:
在这里插入图片描述
3、点进来可以发现里面会有一个设置Initializers的方法,然后查看该方法,就是将Initializers放到一个成员变量的list里面,供启动类来使用。
Spring Boot自动配置讲解_第7张图片
4、那这些Initializers是从哪里来的?我们再点进入getSpringFactoriesInstances查看,发现有一个loadFactoryNames方法,它拿着ApplicationContextInitializer(type参数)和类加载器(classloader参数)进行执行,然后将执行的结果放到了一个Set里面。
Spring Boot自动配置讲解_第8张图片
5、点进入loadFactoryNames方法里,根据ApplicationContextInitializer类型的Class获得到路径名,然后执行了loadSpringFactories方法,根据名字可以猜出应该是加载spring工厂的方法。
在这里插入图片描述
6、点进入loadSpringFactories方法里,这里有三个关键的地方:
Spring Boot自动配置讲解_第9张图片
6.1、第一个是类加载器会根据成员变量来获取urls,我们查看一下这个成员变量是什么:
在这里插入图片描述
是jar包下META-INF目录里面的spring.factories
Spring Boot自动配置讲解_第10张图片
6.2、第二个关键点是url,查看url的详细信息:
在这里插入图片描述
发现就是maven仓库里面spring-boot的jar包(这些jar包就是本项目pom文件里面引入的jar包)。
6.3、第三个关键点它是一个while循环,也就是会遍历所有pom文件里面的jar包,拿到spring.facotries里面的内容。
看一下spring.facotries文件中的格式,等于号前面是接口的名字,后面是接口的实现类。
Spring Boot自动配置讲解_第11张图片
总结一下该方法也就是会获取所有的pom文件里面的jar包中spring.facotries中的内容,然后将放到类型为LinkedMultiValueMap的result中(上面第6点中的图),key为factoryName,value为配置文件中的实现类,最终放到缓存里面。
7、然后返回后执行getOrDefault,因为参数是factoryName(值为org.springframework.context.ApplicationContextInitializer),所以返回的只是org.springframework.context.ApplicationContextInitializer类型的bean:
在这里插入图片描述
8、也就是在初始化的时候会返回这些bean,然后下面在返回org.springframework.context.ApplicationListener类型的bean(续上面第3步骤):
Spring Boot自动配置讲解_第12张图片
这里就不说与咱们要找的类 AutoConfigurationImportSelector 无关的一些内容了,但是在执行到该类之前,依然会返回好多的bean作为SpringAppIication启动类的成员变量,获取bean的方式与上面如出一辙。

重点

当执行到 SpringApplication类中 run方法里面 refreshContext方法的时候,就与我们的自动配置类有关了。下面只讲一下有关 AutoConfigurationImportSelector 类的方法。
在这里插入图片描述
1、先执行到 AutoConfigurationImportSelector 类中的 getImportGroup方法
在这里插入图片描述
2、然后执行到 process方法里面,拿着元数据(有关启动类的信息)去执行里面的getAutoConfigurationEntry方法
Spring Boot自动配置讲解_第13张图片
3、然后走到 getAutoConfigurationEntry方法里,之后执行 getCandidateConfigurations方法,获取有关配置的继承者,也就是与配置文件中org.springframework.boot.autoconfigure.EnableAutoConfiguration注解相关的类。
Spring Boot自动配置讲解_第14张图片
4、然后执行到下面,获取工厂的名字:
Spring Boot自动配置讲解_第15张图片
5、紧接着就是熟悉的步骤,回到了这里,获取org.springframework.boot.autoconfigure.EnableAutoConfiguration注解相关的配置类,然后进行返回即可。
在这里插入图片描述
6、但是需要注意的是,一开始是返回了127条数据,因为进行了过滤,所以最后只返回了23条数据
Spring Boot自动配置讲解_第16张图片
7、执行 return new AutoConfigurationEntry的方法,将返回的23个bean给成员变量List赋值
在这里插入图片描述
8、然后经过重重包装,将这23条数据返回给启动类SpringApplication,进行启动,最终返回给客户端:
Spring Boot自动配置讲解_第17张图片
Spring Boot自动配置讲解_第18张图片
上面没有说重重包装的过程,其实当执行完AutoConfigurationImportSelector 方法之后,会执行AutoConfigurationPackages注解里面的内容,将扫描到配置文件里的bean进行注册,同时还包括上面@Component注解扫描自定的的bean。
所以我们来分析一下@AutoConfigurationPackage注解

@AutoConfigurationPackage

查看该注解有哪些标识:
在这里插入图片描述
可以看到该注解被@Import注解标识,@Import的作用就是直接导入bean,导入bean的类型是AutoConfigurationPackages类的静态内部类Registrar,下面我们来分析什么时候Registrar来发挥作用:
1、在上面AutoConfigurationImportSelector类执行完返回的过程,会走到ConfigurationClassBeanDefinitionReader类中的loadBeanDefinitions方法:
Spring Boot自动配置讲解_第19张图片
2、然后将拿到的配置类进行for循环,如果是启动类的话,就会走进Registrar方法:
在这里插入图片描述
3、最终注册一个BasePackges类来保存启动类所在的包路径名字(packageNames)。
Spring Boot自动配置讲解_第20张图片
Spring Boot自动配置讲解_第21张图片
如有不对,欢迎斧正。

你可能感兴趣的:(SpringBoot,spring,spring,boot,java)