企业级spring-boot案例-自定义Spring Boot Starter

1. 未使用Spring Boot Starter前的情况 在没有 starter 之前,假如我想要在 Spring 中使用 jpa,那我可能需要做以下操作:

在 Maven 中引入使用的数据库的依赖(即 JDBC 的 jar) 引入 jpa 的依赖 在 xxx.xml 中配置一些属性信息 反复的调试直到可以正常运行 需要注意的是,上面的操作在我们每次新建一个需要用到 jpa 的项目的时候都需要重复的做一次。

但在 Spring Boot 中,一切因为 Starter 变得简单

在 pom 文件中引入 spring-boot-starter-data-jpa 在 .properties 文件中配置参数 通过上面两个步骤,配置自动生效,具体生效的 bean 是 JpaRepositoriesAutoConfiguration,自动配置类的名字都有一个特点,叫做 xxxAutoConfiguration。

这就是使用 Spring 框架开发项目带来的一些的问题:

依赖导入问题: 每个项目都需要来单独维护自己所依赖的jar包,在项目中使用到什么功能就需要引入什么样的依赖。手动导入依赖容易出错,且无法统一集中管理 配置繁琐: 在引入依赖之后需要做繁杂的配置,并且这些配置是每个项目来说都是必要的,例如web.xml配置(Listener配置、Filter配置、Servlet配置)、log4j配置、数据库连接池配置等等。这些配置重复且繁杂,在不同的项目中需要进行多次重复开发,这在很大程度上降低了我们的开发效率 而在 Spring Boot 出现之后,它为我们提供了一个强大的功能来解决上述的两个痛点,这就是 Spring Boot 的 starters(启动器)。

2. Spring Boot Starter简介 2.1 什么是Spring Boot Starter(启动器) Spring Boot 通过将我们常用的功能抽取出来,做成的一系列启动器,这些启动器帮我们导入了实现各个功能所需要依赖的全部组件,我们只需要在项目中引入这些 starters,需要的依赖就会全部被导入进来,并且我们通过【约定大于配置】的方式,抛弃繁杂的配置,仅需要通过配置文件来进行少量的配置就可以使用相应的功能。

starter 的实现:虽然不同的 starter 实现起来各有差异,但是他们基本上都会使用到两个相同的内容:ConfigurationProperties 和 AutoConfiguration。因为 Spring Boot 坚信 “约定大于配置” 这一理念,所以我们使用 ConfigurationProperties 来保存我们的配置,并且这些配置都可以有一个默认值,即在我们没有主动覆写原始配置的情况下,默认值就会生效,这在很多情况下是非常有用的。除此之外,starter 的 ConfigurationProperties 还使得所有的配置属性被聚集到一个文件中(一般在 resources 目录下的 application.properties),这样我们就告别了 Spring 项目中众多的 XML 配置。

2.2 Starter 模块整体结构 starter的整体实现逻辑主要由两个基本部分组成:

xxxAutoConfiguration:自动配置类,对某个场景下需要使用到的一些组件进行自动注入,并利用xxxProperties类来进行组件相关配置

xxxProperties:某个场景下所有可配置属性的集成,在配置文件中配置可以进行属性值的覆盖,按照SpringBoot官方的定义,Starer的作用就是依赖聚合,因此直接在starter内部去进行代码实现是不符合规定的,starter应该只起到依赖导入的作用,而具体的代码实现应该交给其他模块来实现,然后在starter中去引用该模块即可,因此整体的starter的构成应该如下图所示:

可见starter模块依赖了两部分,一部分是一些常用依赖,另一部分就是对自动配置模块的依赖,而xxxAutoConfiguration与xxxProperties的具体实现,都封装在自动配置模块中,starter实际是通过该模块来对外提供相应的功能。

2.3 Spring 官方提供的 Starter 和 Starter 命名规范 SpringBoot 提供了非常多的 Starter,下面列出常用的几个:

序号 名称 功能 1 spring-boot-starter-web 支持 Web 开发,包括 Tomcat 和 spring-webmvc 2 spring-boot-starter-redis 支持 Redis 键值存储数据库,包括 spring-redis 3 spring-boot-starter-test 支持常规的测试依赖,包括 JUnit、Hamcrest、Mockito 以及 spring-test 模块 4 spring-boot-starter-aop 支持面向切面的编程即 AOP,包括 spring-aop 和 AspectJ 5 spring-boot-starter-data-elasticsearch 支持 ElasticSearch 搜索和分析引擎,包括 spring-data-elasticsearch 6 spring-boot-starter-jdbc 支持JDBC数据库 7 spring-boot-starter-data-jpa 支持 JPA ,包括 spring-data-jpa、spring-orm、Hibernate 可以看到这些 Starter 的名称都是以 spring-boot-starter 为开头,后面跟着具体的模块名,所有官方的 Starter 遵循相似的命名模式。

根据约定,Spring Boot官方的starter命名要定义为spring-boot-starter-*,自定义或者说第三方的要命名为thirdpartyproject-spring-boot-starter

官方命名空间 前缀:spring-boot-starter- 模式:spring-boot-starter-模块名 举例:spring-boot-starter-web、spring-boot-starter-actuator、spring-boot-starter-jdbc 自定义命名空间 后缀:-spring-boot-starter 模式:模块-spring-boot-starter 举例:mybatis-spring-boot-starter 3. 自定义Spring Boot Starter 如果你想要自己创建一个 starter,那么基本上包含以下几步

3.1 根据 starter 命名规范创建一个 spring boot 项目 创建一个名为config-spring-boot-starter的 spring boot 项目

3.4 编写ConfigProperties.java 创建一个配置文件读取类 ConfigurationProperties 用于保存配置信息(如果你的项目不使用配置信息则可以跳过这一步,不过这种情况非常少见)

@ConfigurationProperties注解使开发人员可以轻松地将整个文件.properties和yml文件映射到一个对象中。编写Properties,应使用唯一的名称空间。不要使用Spring Boot的名称空间(如server,management,spring等)。所以应在所有配置键前面加上自己的名称空间。如我们这里使用的是com.jourwon.config作为配置名称空间。

3.6 编写spring.factories 在resources/META-INF/下创建spring.factories文件,并且把上一步创建的AutoConfiguration类加入 spring.factories 配置文件中

org.springframework.boot.autoconfigure.EnableAutoConfiguration= com.jourwon.spring.boot.config.ConfigAutoConfiguration 1 2 3.7 发布自定义 starter 在自定义 starter 项目根目录执行 mvn install 进行打包安装

3.8 测试自定义 starter 3.8.1 添加config-spring-boot-starter依赖 3.8.4 启动测试 打开浏览器,输入 http://127.0.0.1:8080/configInfo ,你将会看到我们配置的内容。

4. Spring Boot Starter原理 首先说说原理,我们知道使用一个公用的starter的时候,只需要将相应的依赖添加的Maven的配置文件当中即可,免去了自己需要引用很多依赖类,并且SpringBoot会自动进行类的自动配置。

在导入的starter之后,SpringBoot主要帮我们完成了两件事情:

相关组件的自动导入 相关组件的自动配置 这两件事情统一称为SpringBoot的自动配置

那么 SpringBoot 是如何知道要实例化哪些类,并进行自动配置的呢? 下面简单说一下。

首先,SpringBoot 在启动时会去依赖的starter包中寻找 resources/META-INF/spring.factories文件,然后根据文件中配置的Jar包去扫描项目所依赖的Jar包,这类似于 Java 的 SPI 机制。

第二步,根据 spring.factories配置加载AutoConfigure类。

最后,根据 @Conditional注解的条件,进行自动配置并将Bean注入Spring Context 上下文当中。

我们也可以使用@ImportAutoConfiguration({MyServiceAutoConfiguration.class}) 指定自动配置哪些类。

4.1 自动配置原理 4.1.1 自动配置类的获取与注入 我们从主程序入口来探索一下整个过程的原理:

@SpringBootApplication注解内部结构如下图所示:

AutoConfigurationImportSelector :重点看该类中重写的selectImports方法,看下它返回的字符串数组是如何得来的:

我们可以去到上边提到的spring.factories文件中去看一下,找到spring官方提供的spring-boot-autoconfigure包,在其下去找一下该文件:

可以看到这个就是SpringBoot官方为我们提供的所有自动配置类的候选列表。我们可以在其中找到一个我们比较熟悉的自动配置类去看一下它内部的实现:

经验分享 程序员 微信小程序 职场和发展