【JavaWeb】Springboot的四个特性:自动装配

文章目录

  • 一、前言
  • 二、Springboot四个特性
  • 三、Springboot自动装配
    • 3.1 Springboot牛刀小试:整合redis,引入自动装配
    • 3.2 自动装配的思考
      • 3.2.1 自动装配的思考
      • 3.2.2 从静态装配bean实例到动态装配bean实例
    • 3.3 自动装配的模拟
      • 3.3.1 两个bean和两个配置类
      • 3.3.2 MyImportSelector类
      • 3.3.3 @MyEnableConfiguration注解
      • 3.3.4 详细运行流程解释
      • 3.3.5 附加:既可以是配置类,也可以直接是bean类
    • 3.4 从模拟到实际,解析自动装配的底层原理
      • 3.4.1 从模拟到实际,springboot底层实现动态装配
      • 3.4.2 从模拟到实际,redis配置类
      • 3.4.3 Springboot自动装载的核心源码
    • 3.5 springboot自动装配小结
    • 3.6 SPI 设计思想
      • 3.6.1 什么是SPI?
      • 3.6.2 DPI设计思想的demo
  • 四、Springboot自动装配进一步深入
    • 4.1 Starter组件的原理:官方包依赖的条件触发
      • 4.1.1 条件注解引入
      • 4.1.2 官方依赖包中不存在spring.factories
      • 4.1.3 条件注解确保配置类完成配置
      • 附:spring.factories中记录官方包的配置类定位
    • 4.2 demo spring.factories自定义组件的配置类的装载
    • 4.3 demo @ConditionalOnClass等注解实现条件配置
    • 4.4 demo spring-autoconfigure-metadata.properties 实现条件配置
    • 4.5 两种配置方式一起使用
  • 五、小结

一、前言

二、Springboot四个特性

springboot和微服务的关系是什么?
回答:所有的微服务组件,都是集成到springboot上面,spring cloud也是一样,在使用springcloud的时候,它应该和springboot在版本上兼容。

1、第一特性,EnableAutoConfiguration ,译为自动装配

2、第二特性,Starter启动依赖,依赖于自动装配的请求。
3、第三特性,Actuator监控,提供一些endpoint,这些endpoint可以基于http jmx 等形式去进行访问health信息,metrics信息。

4、第四特性,Spring Boot CLI它是为springcloud提供的springboot命令行操作的功能,它通过groovy脚本快速构建springboot的应用,用得很少,一般还是基于idea应用构建springboot应用,略过。

小结:自动装配和启动依赖是不同的,两者关系是启动依赖依赖于自动装配,监控提供一些访问形式。

三、Springboot自动装配

3.1 Springboot牛刀小试:整合redis,引入自动装配

【JavaWeb】Springboot的四个特性:自动装配_第1张图片

【JavaWeb】Springboot的四个特性:自动装配_第2张图片

【JavaWeb】Springboot的四个特性:自动装配_第3张图片

问题:能够实现@Autowired依赖注入的前提是是IOC中存在这个bean的实例,那么是谁装载了这个bean实例?

回答:spring中装载bean实例包括三种方式:xml文件 configuration类 enable注解,现在这三种方式我们都没做,但是为什么springboot可以实现bean装配,这就是springboot的自动装配,完成bean的自动装载,只要写出来@Autowired,自动装配的原理是怎么实现的。

3.2 自动装配的思考

3.2.1 自动装配的思考

【JavaWeb】Springboot的四个特性:自动装配_第4张图片
【JavaWeb】Springboot的四个特性:自动装配_第5张图片

【JavaWeb】Springboot的四个特性:自动装配_第6张图片

springboot为什么能够完成自动装配?
一句话总结,在pom.xml中引入的依赖(即jar包),都被约定好带有统一的格式,都有XxxConfiguration类,使用时springboot直接对其扫描,就完成了装配,但是这是对开发程序员不可见的,所以被称为自动装配。每个第三方的starter里面都有一个配置类XxxConfiguration类,这是一种约定。

【JavaWeb】Springboot的四个特性:自动装配_第7张图片

Springboot自动装载问题1:Spring引擎怎么知道第三方组件starter里面具体配置类在哪里?

Springboot自动装载问题2:如何实现批量扫描配置类XxxConfiguration redis mybatis dubble?

3.2.2 从静态装配bean实例到动态装配bean实例

spring静态装配三种方式:xml文件 Configuration配置类 @Enable模块装配
spring动态装配两种方式:ImportSelector接口 Registator接口

每一个第三方starter里面都有一个配置类XxxConfiguration,Springboot中使用多个第三方组件,如何批量扫描多个配置类XxxConfiguration

答案:批量bean加载机制。spring存在两种动态bean装载机制,一种是ImportSelector接口,一种是Registator接口,都是接口,本文介绍ImportSelector接口。

动态装载:根据运行时上下文的具体运行条件来状态来装载配置类XxxConfiguration,不同于@Conditional。

3.3 自动装配的模拟

这部分给出一个项目,模拟springboot自动装配,项目结构如下:

【JavaWeb】Springboot的四个特性:自动装配_第8张图片

3.3.1 两个bean和两个配置类

给出一个mybatis bean类、mybatis 模拟配置类、redis bean类、redis 模拟配置类

【JavaWeb】Springboot的四个特性:自动装配_第9张图片

【JavaWeb】Springboot的四个特性:自动装配_第10张图片
【JavaWeb】Springboot的四个特性:自动装配_第11张图片

【JavaWeb】Springboot的四个特性:自动装配_第12张图片

3.3.2 MyImportSelector类

模拟ImportSelector实现类,实现ImportSelector接口,返回配置类

【JavaWeb】Springboot的四个特性:自动装配_第13张图片

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        // 在这里去加载所有的配置类
        // 通过某种机制去完成指定路径的配置类的扫描就行?
        // spring只需要知道 package.class.classname 就行了。
        return new String[]{MybatisConfiguration.class.getName(), RedisConfiguration.class.getName()};
    }
}

3.3.3 @MyEnableConfiguration注解

如何让SpringbootApplication知道MyImportSelector返回的配置类?只需要声明一个注解就可以完成。

定义一个注解,@Import(ImportSelector接口实现类.class)
【JavaWeb】Springboot的四个特性:自动装配_第14张图片
SpringApplicationdemoApplication类中使用这个注解
【JavaWeb】Springboot的四个特性:自动装配_第15张图片

在这里插入图片描述

3.3.4 详细运行流程解释

本项目中,其实SpringbootApplication不要使用@MyEnableConfiguration也可以,因为SpringbootdemopageApplication所在包为package com.example.demo;但是,两个bean所在包为package com.example.demo.mybatis 和 package com.example.demo.redis,这样,启动SpringbootdemopageApplication,会扫描所在包及其子包,就扫描到了两个bean。

如果SpringbootdemopageApplication在com.example.demo.springbootdemo,必须配置@MyEnableConfiguration注解,启动的时候,扫描@MyEnableConfiguration注解,然后知道它@Import(MyImportSelector.class),在MyImportSelector.class中,spring才知道两个配置类的路径,才有了下面的装载bean并打印出来。

【JavaWeb】Springboot的四个特性:自动装配_第16张图片

3.3.5 附加:既可以是配置类,也可以直接是bean类

【JavaWeb】Springboot的四个特性:自动装配_第17张图片

貌似MyImportSelector 返回值中直接放bean类会出现重复装配的情况,总之,最好放配置类。

小结:这个实例告诉我们,springboot底层使用ImportSelector接口+注解动态装载,无论第三方组件(项目中com.example.demo.mybatis 和 com.example.demo.redis模拟第三方组件,每一个组件都包括配置类和实体bean)的配置在哪里,都可以用ImportSelector接口找到,并用注解告诉springboot,解决了第一个问题。对于n个配置类(项目中mybatis和redis模拟两个配置类),可以批量配置,不是问题。

注意1:使用@ComponentScan或base-package不可以,它是静态装配,需要把扫描的路径写死,但是在使用一个第三方组件的时候,你是不知道它的bean或配置类在哪里的,这就是静态装配的局限,只能用动态装配。
注意2:使用@Contional 也不仅,仅仅只是一个给出一个判断,装配还是不装配,当然下文我们的有条件配置。

3.4 从模拟到实际,解析自动装配的底层原理

3.4.1 从模拟到实际,springboot底层实现动态装配

【JavaWeb】Springboot的四个特性:自动装配_第18张图片

【JavaWeb】Springboot的四个特性:自动装配_第19张图片

【JavaWeb】Springboot的四个特性:自动装配_第20张图片

【JavaWeb】Springboot的四个特性:自动装配_第21张图片

【JavaWeb】Springboot的四个特性:自动装配_第22张图片

【JavaWeb】Springboot的四个特性:自动装配_第23张图片

**可以看到,springboot的动态装载的底层实现的@SpringBootApplication注解和我们的模拟的时候的自定义注解@MyEnableConfiguration底层是一样的,都是集成ImportSelector接口实现其selectImports返回配置类数组。**难怪刚刚开始的redisTemplate可以自动装配。

【JavaWeb】Springboot的四个特性:自动装配_第24张图片

3.4.2 从模拟到实际,redis配置类

【JavaWeb】Springboot的四个特性:自动装配_第25张图片

3.4.3 Springboot自动装载的核心源码

@Autowird
private RedisTemplate redisTemplate;   // 自动装载

第一,AutoConfigurationImportSelector 自动配置ImportSelector :getAutoConfigurationEntry 获得自动配置/自动装载实体

【JavaWeb】Springboot的四个特性:自动装配_第26张图片
【JavaWeb】Springboot的四个特性:自动装配_第27张图片

【JavaWeb】Springboot的四个特性:自动装配_第28张图片

【JavaWeb】Springboot的四个特性:自动装配_第29张图片

第二,SpringFactoriesLoader 表示 :spring.factories 加载

【JavaWeb】Springboot的四个特性:自动装配_第30张图片

【JavaWeb】Springboot的四个特性:自动装配_第31张图片

【JavaWeb】Springboot的四个特性:自动装配_第32张图片

3.5 springboot自动装配小结

开发程序员使用的时候,只要直接使用

@Autowired
private RedisTemplate<string,string> redisTemplate;  // 自动配置好了的,直接用就好

问题:刚才的项目只是在自己的项目中模拟,那么具体实践中,spring引擎怎么知道具体starter配置类在哪里?

回答:第一,所有starter遵循统一的约定,所有的starter组件,都需要一个META-INF/spring.factories文件,如下:

【JavaWeb】Springboot的四个特性:自动装配_第33张图片
【JavaWeb】Springboot的四个特性:自动装配_第34张图片

【JavaWeb】Springboot的四个特性:自动装配_第35张图片

第二,springboot直接扫描配置文件(org.redis.RedisConfiguration org.mybatis.MybatisConfiguration)就好了,如下图:

【JavaWeb】Springboot的四个特性:自动装配_第36张图片

【JavaWeb】Springboot的四个特性:自动装配_第37张图片
第三,自动装载就完成了。

3.6 SPI 设计思想

3.6.1 什么是SPI?

SPI 全称 Service provider interface ,服务提供接口,这里以各个不同的数据库驱动为例,如图:

【JavaWeb】Springboot的四个特性:自动装配_第38张图片

SPI 就是我们提供接口,接口的具体实现由第三方来做(这里,不同的数据库驱动是不同的,由数据库厂商来完成),Java程序只要导入不同的jar包就可以执行,这就是SPI的扩展,就是服务提供接口的扩展。

为什么说spring.factories也是SPI,spring.factories 是基于key-value键值对的,其中key就是同一个Configuration,value由第三方具体实现;因为每一个starter组件的jar包都有一个Configuration注解,提供一个与springboot沟通接口,其内部具体实现由第三方来做(redis mybatis dubbo),springboot只要导入不同的jar包(redis依赖 mybatis依赖 dubbo依赖)就好。

一句话总结DPI:
DPI 本身包含默认实现,但是也提供扩展点,需要的话可以替换,提高伸缩性和灵活性。

3.6.2 DPI设计思想的demo

DPI设计得以实现需要满足以下条件:

1、需要在classpath目录下创建一个META-INF/services

2、在该目录下创建一个扩展点的全路径名
2.1 文件中填充这个扩展点的实现
2.2 文件编码格式UTF-8

3、ServiceLoader去进行加载

【JavaWeb】Springboot的四个特性:自动装配_第39张图片

【JavaWeb】Springboot的四个特性:自动装配_第40张图片

【JavaWeb】Springboot的四个特性:自动装配_第41张图片

注意事项:META-INF和services目录必须分开创建

【JavaWeb】Springboot的四个特性:自动装配_第42张图片

maven quickstart 项目,maven clean maven install 之后变成jar包;
maven webapp 项目,maven clean maven install 之后变为war包。

四、Springboot自动装配进一步深入

starter组件与自动装配紧密相连,因为所有的第三方的starter组件都是遵循自动装配的约定,提供spring.factories文件,提供配置类给springboot扫描完成自动装配。

4.1 Starter组件的原理:官方包依赖的条件触发

4.1.1 条件注解引入

【JavaWeb】Springboot的四个特性:自动装配_第43张图片

【JavaWeb】Springboot的四个特性:自动装配_第44张图片

4.1.2 官方依赖包中不存在spring.factories

【JavaWeb】Springboot的四个特性:自动装配_第45张图片

对于官方的springboot starter,不存在spring.factories,那么为什么不存在spring.factories,它又是如何加载的?
原来,starter包包括两种,
官方包 spring-boot-starter-xxx 不存在 spring.factories 如spring-boot-starter-data-redis spring-boot-starter-thymeleaf
第三方包 xxx-spring-boot-starter 一定存在spring.factories

以Redis为例,其配置类RedisAutoConfiguration不存在 spring-boot-starter-data-redis 里面 ,而是不存在spring-boot-autoconfigure包,

【JavaWeb】Springboot的四个特性:自动装配_第46张图片

既然如何,springboot又是如何找到配置类RedisAutoConfiguration的呢?
答案是条件注解。

4.1.3 条件注解确保配置类完成配置

【JavaWeb】Springboot的四个特性:自动装配_第47张图片

【JavaWeb】Springboot的四个特性:自动装配_第48张图片

小结,官方包的依赖就是条件触发。

附:spring.factories中记录官方包的配置类定位

【JavaWeb】Springboot的四个特性:自动装配_第49张图片

【JavaWeb】Springboot的四个特性:自动装配_第50张图片
这里面这些都只需要导入依赖就好,只有第三方包才需要自己写spring.factories。

4.2 demo spring.factories自定义组件的配置类的装载

新建maven quickstart项目:autoconfiguredemo

【JavaWeb】Springboot的四个特性:自动装配_第51张图片

【JavaWeb】Springboot的四个特性:自动装配_第52张图片

spring.factories文件中指定配置类路径
【JavaWeb】Springboot的四个特性:自动装配_第53张图片

maven clean maven install 成为一个jar包,给springboot工程去使用

新建一个maven quickstart 工程 springbootcore2,导入依赖

【JavaWeb】Springboot的四个特性:自动装配_第54张图片

【JavaWeb】Springboot的四个特性:自动装配_第55张图片

4.3 demo @ConditionalOnClass等注解实现条件配置

现在在第一个工程Configuration配置类上面使用条件注解,表示要满足某一个条件才装载,就使用 @ConditionalOnClass({RedisOperations.class}) 就好了。

先导入依赖

【JavaWeb】Springboot的四个特性:自动装配_第56张图片

【JavaWeb】Springboot的四个特性:自动装配_第57张图片

【JavaWeb】Springboot的四个特性:自动装配_第58张图片

【JavaWeb】Springboot的四个特性:自动装配_第59张图片

4.4 demo spring-autoconfigure-metadata.properties 实现条件配置

在springboot中存在一个spring-autoconfigure-metadata.properties文件,它也是一种配置文件。
【JavaWeb】Springboot的四个特性:自动装配_第60张图片

这种配置文件只是,使用者需要按要求这样配置,实际上我们自己的工程也可以实现这种配置文件并打成jar包的。

源工程

【JavaWeb】Springboot的四个特性:自动装配_第61张图片

【JavaWeb】Springboot的四个特性:自动装配_第62张图片

【JavaWeb】Springboot的四个特性:自动装配_第63张图片

4.5 两种配置方式一起使用

并不是所有的条件配置都是写在类上面的注解上面的,也可以通过spring-autoconfigure-metadata.properties配置文件去写,且看mybatis

这里是mybatis的条件配置文件 spring-autoconfigure-metadata.properties

【JavaWeb】Springboot的四个特性:自动装配_第64张图片

这里是mybatis的条件注解
【JavaWeb】Springboot的四个特性:自动装配_第65张图片

五、小结

本文介绍Springboot自动装配的特性,从使用redis引入了自动装配,然后理解自动装配、模拟实现、阅读springboot源码,最后引入条件触发和demo实现。

天天打码,天天进步!!!

自动装配模拟工程代码:https://download.csdn.net/download/qq_36963950/12555256

SPI设计思想工程代码:https://download.csdn.net/download/qq_36963950/12555258

自动装配+条件注解+条件配置文件工程代码:https://download.csdn.net/download/qq_36963950/12555260

你可能感兴趣的:(JavaWeb)