目录
定义和目的#
命名规范#
准备阶段#
开发步骤#
一、创建 Starter 项目#
二、导入必要的依赖#
三、编写属性类#
四、自定义业务类#
五、编写自动配置类#
六、编写 spring.factories#
编辑
七、编写配置提示文件#
八、测试 starter#
测试 starter#
一、导入自定义起步依赖
参考资料
定义和目的#
定义:Spring Boot 中的 Starter 是 Spring Boot 相对于传统的 Spring 的优势原因之一。Starter 相当于模块,它能将模块所需要的依赖进行整合并对模块内部的 Bean 根据环境进行自动配置。
使用者在使用 Spring Boot 中的 Starter 的时候,无需进行过多的配置和依赖,Spring Boot 能进行自动扫描并且为对应的模块设置默认值,做到真正的开箱即用。 针对于一些没有封装成 Starter 的依赖,往往经常出现的情况是需要使用者自行进行必要的一些配置。而对于 Starter 来说,会在开发者没有进行配置的情况下为模块中的依赖配置默认值;如果开发者想要自行配置,大多数只需要在 yml 配置文件中配置对应的键值对即可。
目的:封装 Starter 的目的主要是为了将独立于业务之外的配置模块进行集成,方便其他工程在需要使用的时候直接在 pom 中导入依赖,避免需要直接进行代码的硬拷贝而重新集成,也减少了硬拷贝可能带来的依赖版本冲突问题,让 Spring Boot 做到真正的开箱即用。
命名规范#
- Spring Boot 官方开发的 Starter 的命名规则为
spring-boot-starter-{name}
,例如:spring-boot-starter-web - 第三方的 Starter 官方推荐的命名规则为
{name}-spring-boot-starter
,例如:mybatis-spring-boot-starter
准备阶段#
在这个阶段我们需要知道一些 Starter 开发中常用的注解,减少使用 xml 配置文件。Spring Boot 在自动装配的过程中是通过扫描 spring.factories 文件加载自动配置类,自动配置类中定义了各种运行时判断条件,这些判断条件的存在减少了依赖冲突的产生,也丰富了 Starter 的扩展功能。
- 属性映射注解
- @ConfigurationProperties:配置文件属性值和实体类的映射
- @EnableConfigurationProperties:和 @ConfigurationProperties 配合使用,把 @ConfigurationProperties 修饰的类加入 IoC 容器。
- 配置bean注解
- @Configuration:标识该类为配置类,并把该类注入 ioc 容器
- @Bean:一般在方法上使用,声明一个 Bean,bean 名称默认是方法名称,类型为返回值。
- 条件注解
- @Conditional:是根据条件类创建特定的 Bean ,条件类需要实现 Condition 接口,并重写 matches 接口来构造判断条件。该注解是 Spring 4 新提供的注解,按照一定的条件进行判断,满足条件给容器注册 Bean。
- @ConditionalOnBean:容器中存在指定bean,才会实例化一个Bean
- @ConditionalOnMissingBean:容器中不存在指定bean,才会实例化一个Bean
- @ConditionalOnClass:系统中有指定类,才会实例化一个Bean
- @ConditionalOnMissingClass:系统中没有指定类的 Bean 信息,才会实例化一个Bean
- @ConditionalOnExpression:当SpEl表达式为true的时候,才会实例化一个Bean
- @AutoConfigureAfter:在某个bean完成自动配置后实例化这个bean
- @AutoConfigureBefore:在某个bean完成自动配置前实例化这个bean
- @ConditionalOnJava:系统中版本是否符合要求
- @ConditionalOnSingleCandidate:当指定的Bean在容器中只有一个,或者有多个但是指定了首选的Bean时触发实例化
- @ConditionalOnResource:类路径下是否存在指定资源文件
- @ConditionalOnWebApplication:是 web 应用
- @ConditionalOnNotWebApplication:不是 web 应用
- @ConditionalOnJndi:JNDI 指定存在项
- @ConditionalOnProperty:配置 Configuration 的加载规则
- prefix:配置属性名称的前缀。
- value:数组,获取对应property名称的值,与name不可同时使用。
- name:数组,可与prefix组合使用,组成完整的配置属性名称,与value不可同时使用。
- havingValue:比较获取到的属性值与havingValue给定的值是否相同,相同才加载配置。
- matchIfMissing:缺少该配置属性时是否可以加载。如果为true,没有该配置属性时也会正常加载;反之则不会生效。
开发步骤#
一、创建 Starter 项目#
注意:在创建 Initializr 项目之后,要删除 main 启动类和 test 文件夹。
在选择起步的时候的依赖时,不需要勾选任何依赖。
https://start.spring.io/
二、导入必要的依赖#
注意:在第一步删除了启动类之后,需要去除 pom 文件中 maven 打包插件 spring-boot-maven-plugin。
这一部分中,为了适配大多数的项目,建议将 JDK 版本设置为 1.8。
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.marion.demo</groupId>
<artifactId>demo-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo-spring-boot-starter</name>
<description>自定义spring-boot-start封装</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Spring Boot 的自动装配所需要的依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置文件点击可以跳转实体,主要是为了适配 IDEA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
三、编写属性类#
我们需要对 Starter 进行配置信息类进行定义,为了和配置文件进行映射,能够读取 yml 或者 properties 文件中的配置属性。
主要用到的注解是 @ConfigurationProperties ,该注解能够帮我们完成映射工作。
package com.marion.demo.springbootstarter.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "demo.config")
public class DemoProperties {
private String name = "Hello Starter!";
private int age = 8;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
四、自定义业务类#
在这一部分可以自定义一些用于获取配置文件信息进行业务操作的业务类。
package com.marion.demo.springbootstarter.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "demo.config")
public class DemoProperties {
private String name = "Hello Starter!";
private int age = 8;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
五、编写自动配置类#
注意:这里配置一个 web 应用才能注入,并且 demo.config.flag 的值是否为 true 或者不配置该 key 才能注入 DemoService 服务。自动配置类遵循的命名规范是 XxxAutoConfiguration。
package com.marion.demo.springbootstarter;
import com.marion.demo.springbootstarter.config.DemoProperties;
import com.marion.demo.springbootstarter.service.DemoService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
// 当存在某个类时,此自动配置类才会生效
@ConditionalOnClass(value = {DemoService.class})
// 导入我们自定义的配置类,供当前类使用
@EnableConfigurationProperties(value = DemoProperties.class)
// 只有非web应用程序时此自动配置类才会生效
@ConditionalOnWebApplication
// 判断demo.config.flag的值是否为“true”, matchIfMissing = true:没有该配置属性时也会正常加载
@ConditionalOnProperty(prefix = "demo.config", name = "flag", havingValue = "true", matchIfMissing = true)
public class DemoAutoConfiguration {
/**
* @param demoProperties 直接方法签名入参注入DemoProperties,也可以使用属性注入
* @return DemoService 类
*/
@Bean
@ConditionalOnMissingBean(DemoService.class)
//@ConditionalOnProperty(prefix = "demo.config", name = "flag", havingValue = "true", matchIfMissing = true)
public DemoService demoService(DemoProperties demoProperties) {
DemoService demoService = new DemoService();
//把获取的信息注入
demoService.setName(demoProperties.getName());
demoService.setAge(demoProperties.getAge());
return demoService;
}
}
六、编写 spring.factories#
在 resource/META-INF/
下面创建 spring.factories
文件,把自动配置类 DemoAutoConfiguration 配置到 org.springframework.boot.autoconfigure.EnableAutoConfiguration 的 key 下,Spring Boot 启动时会自动加载该文件并根据条件装配。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.marion.demo.springbootstarter.DemoAutoConfiguration
如果使用springboot2.7以上
创建META-INF/spring/
org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.marion.demo.springbootstarter.DemoAutoConfiguration
七、编写配置提示文件#
additional-spring-configuration-metadata.json
配置 additional-spring-configuration-metadata.json
文件后,在开发人员的 IDE 工具使用个人编写的配置读取很有效的在application.properties
或application.yml
文件下完成提示。
配置详细格式参数可查看文档
{
"properties": [
{
"name": "demo.config.name",
"type": "java.lang.String",
"defaultValue": "hello 默认值!这里配置的是提示,真正默认值在Properties里面",
"description": "这是字符串名称啊."
},
{
"name": "demo.config.age",
"defaultValue": 18,
"description": "这是int类型的年龄啊.",
"deprecation": {
"reason": "过时原因.",
"replacement": "替代key是:demo.config.age22",
"level": "warning"
}
}
]
}
spring-configuration-metadata.json
spring-configuration-metadata.json
代码量挺大的,为了方便我们可以通过IDE来生成,这里使用的是idea。
在 IDEA 设置中搜索 Annotation Processors,接下来勾住 Enable annonation processing 就完成了。 在编译打包后的文件中看到自动生成的 **spring-configuration-metadata.json**
。这个文件不用我们编写。
八、测试 starter#
编写完毕之后,我们在 maven 控制台执行 clean、compiler、package、install 的操作。
在这一步发现一些问题,在进行打包的时候,发现 test 文件夹下的类提示没有依赖。直接将 test 文件夹删除即可。
新建项目:demo-test-spring-boot-starter 进行测试。
测试 starter#
编写完毕之后,我们在 maven 控制台执行 clean、compiler、package、install 的操作。
在这一步发现一些问题,在进行打包的时候,发现 test 文件夹下的类提示没有依赖。直接将 test 文件夹删除即可。
新建项目:demo-test-spring-boot-starter 进行测试。
一、导入自定义起步依赖
直接运行测试项目的启动类,提示错误:没有定义好 DemoService 的类,推荐定义一个同名的 Bean。
参考资料
【Spring】-springboot 自定义starter封装
spring-boot-starter ~ 封装 简要版_springboot 封装starter-CSDN博客
Spring Boot 3.x 自动配置详解-腾讯云开发者社区-腾讯云
在SpringBoot3中spring.factories配置不起作用的原因和解决方法_springboot3 spring.factories-CSDN博客