IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 【自定义Spring-Boot-Starter及原理详解】 -> 正文阅读

[Java知识库]【自定义Spring-Boot-Starter及原理详解】

定义

首先阐述一下Spring-Boot-Starter的概念:

Starter POMs are a set of convenient dependency descriptors that you can include in your application. You get a one-stop-shop for all the Spring and related technology that you need, without having to hunt through sample code and copy paste loads of dependency descriptors. For example, if you want to get started using Spring and JPA for database access, just include the spring-boot-starter-data-jpa dependency in your project, and you are good to go.

简单来说,就是指Starter是一组依赖的组合,类似于插件。

作用

在传统的项目中,我们想使用MyBatis依赖,则必然要引入依赖、编写xml配置文件等等操作。在你开下一个项目时还是需要这样操作,尤其是复杂的xml。

而在引入Starter后,这些操作都可以舍弃,由Starter自主完成。当我们引入 mybatis-spring-boot-starter 依赖时,我们也只需要在配置文件中编写对应的配置,不需要什么其他操作,都由Starter完成。

简而言之,Starter是一个SpringBoot项目,里面集成了我们所需要的功能及依赖,很多操作在这个项目中已经完成,所以我们不需要自己实现功能,并且也可以解决依赖版本的问题,我们不需要关心每个依赖,全部统一进行管理。

并且,在Starter中,通常会通过@ConfigurationProperties注解使所有的配置属性集中到全局配置文件 application.yml 中,这样就使我们告别了各种各样的xml配置。

命名规范

如果我们要自定义Starter,那么要遵循一定的规范,Spring为Starter制定了一些命名方面的规范(详情请看Spring-Boot-Starter命名规范)。

官方Starter命名为:

spring-boot-starter-data-jpa


自定义Starter命名为:

xxx-spring-boot-starter,例如 mybatis-spring-boot-starter


当然想自定义Starter,则了解SpringBoot自动配置原理必不可少。

自动配置原理

首先,在启动类中的 @SpringBootApplication 注解中,存在着一个 @EnableAutoConfiguration 注解,而在这个注解里,又有一个 @Import(AutoConfigurationImportSelector.class) 注解,该注解表示将这个类引入进Spring容器中,原理就在这个类中。

在这里插入图片描述


在这个类中,有一个 getCandidateConfigurations() 方法,用来获取所有的候选配置,其实就是扫描所有自动配置类,返回的是配置类全限定名的集合。

在这里插入图片描述


点进 SpringFactoriesLoader.loadFactoryNames()方法,我们接着往下看:

在这里插入图片描述

在方法中的描述,我们可以看出,它负责从 META-INF/spring.factories 文件中加载自动配置类的全限定名。

而具体的实现却在 loadSpringFactories() 方法中:

在这里插入图片描述


看,这不就相当于SPI机制吗,在Starter(服务提供者)引入进来后,SpringBoot(服务发现者)自动对其 META-INF/spring.factories 文件中的内容进行扫描,并根据全限定名进行加载。

而在将自动配置类加载进容器时,很多Starter通常会进行校验及Bean加载的先后顺序,也就是条件注解 @Condition,我们简单看一下MyBatis的:

在这里插入图片描述


  1. 首先是 @ConditionalOnClass 注解,他表示在其中指定的类必须存在,也就是说,mybatis-spring-boot-starter 依赖于 org.mybatis 这个Jar,如果该Jar (org.mybatis) 不存在,例如被我们在依赖管理中移除掉了,那么这个Starter的自动配置也不会生效。
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})

  1. @EnableConfigurationProperties 注解,该注解表示启用某个配置文件类,而配置文件类的作用是将全局配置文件的配置绑定到某一个类中,比如 MybatisProperties.class
@EnableConfigurationProperties({MybatisProperties.class})

???MybatisProperties.class:
在这里插入图片描述

???全局配置文件:
在这里插入图片描述


只要通过前缀,即可声明其配置,而配置文件类可以将属性绑定到该类中,但是必须要通过 @EnableConfigurationProperties 启用才能生效。

  1. @AutoConfigureAfter 注解,顾名思义,本类加载的顺序要比里面定义的类要靠后,这样做也是有目的的,比如说 MybatisAutoConfiguration 配置类中有一个成员是由 DataSourceAutoConfiguration 配置类注入到Spring容器的,而且前者使用的还是构造器注入,那么则需要约定顺序,先注入 DataSourceAutoConfiguration 和其中的Bean,再注入 MybatisAutoConfiguration 类。类似于 @DependsOn。
@AutoConfigureAfter({DataSourceAutoConfiguration.class})

既然已经讲清楚了这些,就来说说如何实现Spring-Boot-Starter。


实现

  1. 先创建一个项目,命名为 xxx-spring-boot-starter。

  1. 在Pom文件中,添加两个依赖,分别是SpringBoot的核心启动器,以及配置文件类的配置描述(后面讲解)。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <artifactId>demo-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starters</artifactId>
        <version>2.3.5.RELEASE</version>
    </parent>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

</project>

  1. 随后,简单创建一个自动配置类(需要在自动配置类中将所有需要注入的Bean注入进来)
// 配置类
@Configuration
// 启用配置文件类
@EnableConfigurationProperties(DemoProperties.class)
public class DemoAutoConfiguration {

    private final DemoProperties demoProperties;

    public DemoAutoConfiguration(DemoProperties demoProperties) {
        this.demoProperties = demoProperties;
    }

    @Bean
    public DemoHandler demoHandler() {
        return new DemoHandler(demoProperties);
    }
}

  1. 配置文件类(Get Set方法要齐全,不然无法注入属性)
// 在这里规定该配置文件类的配置前缀
@ConfigurationProperties(prefix = "student.info")
public class DemoProperties {

    /**
     * 学生姓名
     */
    private String name;

    /**
     * 学生年龄
     */
    private Integer age;

    /**
     * 学生性别,男-true,女-false
     */
    private Boolean sex;
}

  1. 演示处理(不要贴@Component @Service等注解,非相同路径,Spring是不会扫描的)
public class DemoHandler {

    private static final Logger log = LoggerFactory.getLogger(DemoHandler.class);

    private final DemoProperties demoProperties;

    public DemoHandler(DemoProperties demoProperties) {
        this.demoProperties = demoProperties;
    }

    public void print() {
        log.info("学生姓名:{}, 学生年龄:{}, 学生性别:{}",
                demoProperties.getName(), demoProperties.getAge(), demoProperties.getSex() ? "男" : "女");
    }
}

  1. 项目结构如下:

在这里插入图片描述


接下来,就可以在项目中引用 DemoHandler类进行执行了。

在这里插入图片描述

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Resource
    private DemoHandler demoHandler;

    @PostConstruct
    public void run() {
        demoHandler.print();
    }

}

配置(可以看到,该配置是使用的 DemoProperties 类,包括注释也有提示):

在这里插入图片描述


结果(确实是将DemoHandler类注入进容器中,并且将我们的配置也读取出来了):

在这里插入图片描述



回到刚刚说的一个问题:spring-boot-configuration-processor依赖是什么?

其实,我们在配置文件中,定义配置时,如果没有这个依赖,配置是不会有提示功能的。

在这里插入图片描述


这个功能归功于这个文件,它属于META-INF\spring-configuration-metadata.json,拥有这个文件,才能出现配置文件中的提示功能,在这个文件中约定了配置的类型、名称、描述以及所属的类,而我们如果自定义该文件,未免太过麻烦。因为如果你有很多配置,那么你就要写很多东西了,而这个依赖可以帮助我们生成该文件,避免我们手写。
(详情可以看下这个 spring-boot-configuration-processor

在这里插入图片描述


问题:

  1. 所有需要加载的类都需要在自动配置类中注入,因为只有spring.factories文件中定义的类才会被加载。

  2. 如果你需要使用 mvn install安装到本地仓库,请不要在Pom文件中定义 packaging,会导致失败。
    在这里插入图片描述

  3. 配置文件类中可以约定默认值,如果使用者不指定新值的话,默认使用该默认值。


总结

每个Starter都描述一种或多种功能,它会将所有用到的依赖包含进来,首先避免了开发者手动导入依赖的情况。同时,我们可以在Starter中使用Spring的各种功能,例如切面,事件等,因为Starter严格来说就是一个SpringBoot项目。并且我们不需要再指定xml了,在Starter中,已经帮助我们自动做完了这些工作,我们只需要提供配置即可,同时,也不需要关心其如何实现。只需要像插件一样安装上去即可运行。easy~

另外,可以看看我简单实现的一个canal-spring-boot-starter,基于Canal原生API实现,借鉴了一些开源项目的思路,也比较简单,希望对你有所帮助。




  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-10-22 21:01:38  更:2022-10-22 21:06:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年3日历 -2025/3/10 18:23:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码