SpringBoot 札记(自动装配原理)

目标:

了解 SpringBoot 的自动装配原理


学习步骤:

1、了解 父依赖管理特性
2、自动配置包 spring-boot-autoconfigure
3、自动配置原理

一、SpringBoot 父依赖管理特性

SpringBoot 札记(自动装配原理)_第1张图片

新建完项目,为什么我们只导入了这个包 就可以运行web项目了呢 ? 连依赖版本号都不用 ?

现实肯定不是这样子的,我们点进去 spring-boot-starter-web 看看

SpringBoot 札记(自动装配原理)_第2张图片

可以看到一个 spring-boot-dependencies 依赖,进去看看

往下拉可以看到一大堆版本信息

SpringBoot 札记(自动装配原理)_第3张图片

同样的,我们在 pom.xml 文件的开头也可以进入依赖管理文件

SpringBoot 札记(自动装配原理)_第4张图片

如果进不去,就降低版本

SpringBoot 札记(自动装配原理)_第5张图片

SpringBoot 札记(自动装配原理)_第6张图片
SpringBoot 札记(自动装配原理)_第7张图片
看了 spring-boot-dependencies 之后发现:核心依赖在父工程中!所以我们才不需要声明版本信息

我们在写或者引入一些 SpringBoot 依赖的时候,不需要指定版本,就因为有这些版本仓库

此时就有一个问题了 我们先看看这个情况

SpringBoot 札记(自动装配原理)_第8张图片

很大一部分公司MySQL用的是5版本的咋整?

肯定不能在这个文件进行修改呀,得在pom.xml文件中进行版本指定(重新覆盖)

比如还是想用 MySQL5版本

SpringBoot 札记(自动装配原理)_第9张图片
SpringBoot 札记(自动装配原理)_第10张图片

上面指定MySQL的版本后 , 下面引入同样无需写版本号

<dependency>
	<groupId>mysqlgroupId>
	<artifactId>mysql-connector-javaartifactId>
dependency>

此时查看依赖项目版本信息

SpringBoot 札记(自动装配原理)_第11张图片

或者,还可以利用如下写法 指定MySQL的版本号信息,直接写版本号,但是这样子不容易做项目全局控制,一般公司的项目都有标明用什么技术的什么版本,所以我们一般都是在最上面的 属性中声明项目所需版本信息

<dependency>
	<groupId>mysqlgroupId>
	<artifactId>mysql-connector-javaartifactId>
	<version>5.1.47version>
dependency>

二、自动配置包 spring-boot-autoconfigure

我们可以通过这个WEB启动器来挖掘 SpringBoot的自动配置包在哪里

SpringBoot 札记(自动装配原理)_第12张图片

进入该文件,可以看到还有一个spring-boot-starter启动器

SpringBoot 札记(自动装配原理)_第13张图片

进入这个启动器,又可以看到一个spring-boot-autoconfigure包 翻译过来就是自动配置类

SpringBoot 札记(自动装配原理)_第14张图片

SpingBoot 所有的自动配置功能都在 spring-boot-autoconfigure 包中,项目中有很多 starter 启动器,SpringBoot 会按需加载所有的自动配置项,只有引入了这个 starter 启动器,该场景下的自动配置才会开启

三、自动配置原理

3-1、引导加载自动配置类

还是从 Main 方法着手

SpringBoot 札记(自动装配原理)_第15张图片

查看 核心注解 @SpringBootApplication 注解

SpringBoot 札记(自动装配原理)_第16张图片

发现它其实就是下面 三个注解的整合

  • @SpringBootConfiguration
  • @EnableAutoConfiguration
  • @ComponentScan

核心:换句话说就是将 @SpringBootApplication 注解替换成 这三个注解,程序照样正常运行SpringBoot 札记(自动装配原理)_第17张图片


3-2、@SpringBootConfiguration 注解

进去看看

SpringBoot 札记(自动装配原理)_第18张图片

也就是说 这个注解 存在的意义 就是让我们的 主类 变成配置类 (此时主类就变成核心配置类)


3-3、@EnableAutoConfiguration 注解 (重点:开启自动配置功能)

点进去一看,发现是两个注解的合成

SpringBoot 札记(自动装配原理)_第19张图片


3-3-1、先看看 @AutoConfigurationPackage 注解

SpringBoot 札记(自动装配原理)_第20张图片

@AutoConfigurationPackage 注解的 这个 @Import 只是给容器中导入一个AutoConfigurationPackage.Registrar 组件

在容器中 导入一个注册类 Registrar , 进去看看

SpringBoot 札记(自动装配原理)_第21张图片

此时它利用 Registrar 给容器中导入一些组件(批量导入)

new PackageImports(metadata).getPackageNames() 就是在获取 Main类 的所在的包名 com.csnz , 转换为数组

所以 @AutoConfigurationPackage 注解 的作用就是 将Main主类包下的所有组件进行导入(即 com.csnz 包下)


3-3-2、再看 @Import注解

SpringBoot 札记(自动装配原理)_第22张图片

发现 他是导入一个 AutoConfigurationImportSelector 包 ,这个包的作用也是 批量导入

进入此类中,往下拉可以看到一个方法

此方法 决定了我们需要导入的bean,它会封装成一个数组返回

SpringBoot 札记(自动装配原理)_第23张图片

进入这个 获取自动配置入口 的方法看看

SpringBoot 札记(自动装配原理)_第24张图片

此方法还有一个需要注意到的点,就是 获取候选配置方法

SpringBoot 札记(自动装配原理)_第25张图片

进去瞧瞧

SpringBoot 札记(自动装配原理)_第26张图片

看看 Spring工厂加载机制的 loadFactoryNames 方法

在这里插入图片描述
SpringBoot 札记(自动装配原理)_第27张图片

SpringBoot 札记(自动装配原理)_第28张图片

查看资源,发现他是从 META-INF/spring.factories 位置加载文件的,默认扫描我们当前系统里面所有 META-INF/spring.factories 位置的文件,因为有众多包拥有此文件,所以我们只需关注一个包即可,那就是自动配置包 spring-boot-autoconfigure-2.3.7.RELEASE.jar

那这个自动配置包在哪里呢 ?

SpringBoot 札记(自动装配原理)_第29张图片

进入文件可以看到 Auto Configure 下有大量的自动配置类

文件里面写死了 SpringBoot 一启动就要给容器中加载的所有配置类

SpringBoot 札记(自动装配原理)_第30张图片


3-3-3、是否一启动就导入全部自动配置项呢?

肯定不是的,SpringBoot 会按需开启自动配置项

SpringBoot 札记(自动装配原理)_第31张图片

虽然我们 127 个场景的所有自动配置启动的时候默认全部加载,但是你打开具体文件,他里面是按照条件装配规则来决定是否加载的(@Conditional注解),所以最终是会按需进行配置的


3-4、 @ComponentScan 注解

SpringBoot 札记(自动装配原理)_第32张图片

其实就是用于指定 spring 在初始化容器时要扫描的包,这在学习Spring初期注解就涉及到了


自动配置总结:

1. SpringBoot 先加载所有的自动配置类 xxxAutoConfiguration (比如批处理)
SpringBoot 札记(自动装配原理)_第33张图片

2. 每个自动配置类 会根据里面内部的条件 决定是否注入Bean,每个文件中都默认绑定了配置文件指定的值,从xxxProperties类中拿,而xxxProperties类又和配置文件进行了绑定SpringBoot 札记(自动装配原理)_第34张图片
SpringBoot 札记(自动装配原理)_第35张图片

3. 生效的配置类就会给容器中装配很多组件
4. 只要容器中有这些组件,相当于这些功能就具有了
5.实现定制化配置

  • 5-1. 第一种方式:用户自己 写方法 @Bean 替换底层的组件
  • 5-2. 第二种方式:用户查看此组件是获取配置文件的什么值就去修改,根据组件文件中绑定的前缀信息去application.properties文件中修改即可
  • 5-3. 流程:xxxAutoConfiguration ==> 对应的组件 ⇒ xxxProperties类中拿值 ==> 在 application.properties中修改

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