一. 自定义Starter 基础知识
一.一 自定义Starter
以前我们在学习 Spring 时,依赖的依赖,都是某一个具体的依赖信息。在Spring Boot 阶段,我们导入的依赖 的 artifactId 都拥有 starter。如: mybatis-spring-boot-starter pagehelper-spring-boot-starter 等.
这些其实,都是比较官方的自定义 Starter。
在日常开发里面,对于独立于业务模块的一些功能,常常会放置在一个单独的包里,
如 切面实现日志功能, 在项目A里面使用到了,在项目B 里面也使用到了,以前的做法,是什么样子的呢? 通常将这个日志功能实现的代码复制A项目里面,同时复制到B项目里面,这样 A项目便拥有了日志的功能,B项目也拥有了日志的功能。如果实现日志功能的代码发生改变,那么项目A,项目B都需要进行修改。如果能够将 这个切面实现日志功能的代码 提取出来,变成一个 依赖的jar包,项目A,项目B直接导入依赖,便可以使用,那就好了。
我们可以通过自定义Starter 实现这些功能。
SpringBoot提供的starter以spring-boot-starter-xxx的方式命名的。
官方建议自定义的starter使用xxx-spring-boot-starter命名规则。以区分SpringBoot生态提供的starter。
这一章节,先简单实现一个基础的自定义Starter 的功能。
下一章节,老蝴蝶带着大家通过自定义 Starter 实现切面日志记录的功能。
一.二 自定义Starter 需要什么
我们自定义 Starter 需要什么呢? 想一想,以前的配置, 如 redis的配置,mysql数据库的配置信息.
1.我们需要传入一些参数,可以更改配置 (在application.yml 中配置参数) ,同时有默认的配置参数.
2.有一个功能实现,可以获取到用户传入的配置参数,使用这些配置参数,可以实现我们想要的功能.
3.动态的进行配置,热插拔效果。达到 我们拥有这个自定义starter,就拥有这些东西,没有自定义starter,就没有这些东西的效果。
4.自动化的配置,可以被 SpringBoot 官方识别并承认 (需要固定的格式).
我们需要拥有这些东西,才可以进行自定义 Starter
二. 实现用户信息打印的 自定义 Starter
先创建一个默认的 Maven 项目, 非 SpringBoot 项目。
主要依靠的是 SpringBoot 的自动配置
我们做一个简单的,配置信息打印的 Starter
1,2,3,4 其实对应的就是 一.二 部分的 1,2,3,4
二.一 pom.xml 导入依赖
<?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> <groupId>top.yueshushu</groupId> <artifactId>starter</artifactId> <version>1.0-SNAPSHOT</version> <name>ButterflyStarter</name> <dependencies> <!--添加自动配置的依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> <version>2.2.2.RELEASE</version> </dependency> <!--添加配置文件引用的依赖信息--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <version>2.2.2.RELEASE</version> <optional>true</optional> </dependency> </dependencies> </project>
除些之外,不需要引入其他的.
二.二 属性类接收用户自定义参数
在 application.yml 中配置参数,通常有很多个,且格式固定, 我们常常通过一个配置属性类进行接收用户的自定义参数。我们传入 名称,年龄,描述 三个基础的参数 信息.
UserProperties.java
package top.yueshushu.starter.mode; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationPropertiesScan; import java.io.Serializable; /** * @ClassName:User * @Description 自定义的一个实体 * @Author zk_yjl * @Date 2021/10/22 16:57 * @Version 1.0 * @Since 1.0 **/ /** 不建议引用 @Data lombok 第三方插件 * @author yjl */ @SuppressWarnings("serial") @ConfigurationProperties(prefix = "butterfly") public class UserProperties implements Serializable { /** 定义 final 常量,用于默认值 */ private final String DEFAULT_NAME="两个蝴蝶飞"; private final Integer DEFAULT_AGE=26; private final String DEFAULT_DESCRIPTION="一个快乐的程序员"; /** 定义属性,使用默认值. */ private String name=DEFAULT_NAME; private Integer age=DEFAULT_AGE; private String description=DEFAULT_DESCRIPTION; /** 提示默认的构造方法 */ public UserProperties() { } public UserProperties(String name, Integer age, String description) { this.name = name; this.age = age; this.description = description; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + ", description='" + description + '\'' + '}'; } }
二.三 做什么, 要实现的功能
我们拿到用户的自定义参数 (没有的话,走默认的参数)后,要做实现事情,即要实现的功能.
UserPropertiesService.java
package top.yueshushu.starter.service; import java.util.logging.Logger; /** * @ClassName:UserService * @Description 用户提示的服务,表示有这一个类。 * @Author zk_yjl * @Date 2021/10/22 17:02 * @Version 1.0 * @Since 1.0 **/ public class UserPropertiesService { //定义日志 Logger logger=Logger.getLogger(UserPropertiesService.class.getSimpleName()); //参数信息,自定义starter 提供的全部的参数信息。 private String name; private Integer age; private String description; public UserPropertiesService() { } // 接收参数 public UserPropertiesService(String name,Integer age,String description) { this.name=name; this.age=age; this.description=description; } /** * 要实现的功能点, 这儿只做一个简单的打印。 * @date 2021/10/29 14:30 * @author zk_yjl * @param * @return void */ public String println(){ String message = String.format("大家好,我叫: %s, 今年 %s岁, 个人描述: %s", name, age,description); logger.info(">>>用户的信息:"+message); return message; } }
二.四 动态热插拔配置
主要是将 这个 XxxService 管控起来。
UserPropertiesServiceConfiguration.java
package top.yueshushu.starter.configuration; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import top.yueshushu.starter.mode.UserProperties; import top.yueshushu.starter.service.UserPropertiesService; /** * @ClassName:UserServiceConfiguration * @Description 用户Service类的配置信息 * @Author zk_yjl * @Date 2021/10/22 17:12 * @Version 1.0 * @Since 1.0 **/ //表示是一个配置类 @Configuration //用户输入的参数信息,可以放置到 UserProperties参数里面。一一对应起来 @EnableConfigurationProperties(UserProperties.class) //存在某个条件类时触发, 即寻找到 UserPropertiesService.class时,才生效 @ConditionalOnClass(UserPropertiesService.class) public class UserPropertiesServiceConfiguration { @Autowired private UserProperties userProperties; @Bean public UserPropertiesService userPropertiesService(){ //注意,当条件触发时,才会创建 Bean UserPropertiesService userService=new UserPropertiesService( userProperties.getName(), userProperties.getAge(), userProperties.getDescription() ); return userService; } }
二.五 配置,能被 SpringBoot 官方承认
必须要进行自动装配,否则这些东西,不被 SpringBoot 官方承认,那么在SpringBoot 项目里面进行引用,就找不到,造成功能不生效.
在 resources 目录下 创建 META-INF 目录,下面放置 spring.factories 文件 (必须叫这个名字)
# 添加配置信息,后面跟的是 自定义的那个configuration的全限定类名 org.springframework.boot.autoconfigure.EnableAutoConfiguration=top.yueshushu.starter.configuration.UserPropertiesServiceConfiguration
现在,这个自定义配置的 ButterflyStarter 就算了成功了。
将其进行打包,安装到本地仓库 (老蝴蝶这儿是通过 mvn clean install 命令实现的)
也可以通过 Lifecycle 生命周期按照进行实现
二.六 测试自定义 Starter
新创建一个 SpringBoot 的项目, StarterApply, 可以正常的启动和访问即可。
二.六.一 pom.xml 中添加依赖
除了 SpringBoot 该有的依赖外,导入刚才 install 生成的自定义Starter 依赖
<!--添加我们自定义的依赖--> <dependency> <groupId>top.yueshushu</groupId> <artifactId>starter</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
二.六.二 测试自定义Starter
在 StarterApply 项目里面,添加 StarterTest 测试类,进行测试
package top.yueshushu.learn; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.test.context.junit4.SpringRunner; import top.yueshushu.condition.Animal; import top.yueshushu.condition.JavaAnimalConfig; import top.yueshushu.starter.service.UserPropertiesService; /** * @ClassName:StarterTest * @Description TODO * @Author zk_yjl * @Date 2021/10/22 17:26 * @Version 1.0 * @Since 1.0 **/ @RunWith(SpringRunner.class) @SpringBootTest public class StarterTest { @Autowired private UserPropertiesService userPropertiesService; @Test public void starterPrintlnTest(){ String message = userPropertiesService.println(); System.out.println("Apply项目输出信息:"+message); } }
二.六.二.一 进行测试
此时, application.yml 配置文件里面,没有关于自定义 Starter 的配置信息
进行测试,发现可以打印, 但是出现了乱码。 是 starter 本身出现的乱码。
二.六.二.二 解决 Starter 乱码问题
在 自定义的Starter pom.xml 添加编译插件,设置编码为 UTF-8
<!-- spring boot 添加编辑方式--> <build> <plugins> <!-- 打包成可执行jar,防止中文乱码,必须要下面这一个插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> <encoding>utf-8</encoding> </configuration> </plugin> </plugins> </build>
重新 mvn clean install ,然后刷新依赖即可。
解决了中文乱码的问题,
自定义 starter 里面的 日志信息会输出,同时项目里面的输出打印语言也生效。 输出的信息,是默认的信息
二.六.二.三 用户自定义参数测试
在 application.yml 中, 输入 butt 发现,有相应的属性提示
输入自定义的参数信息
butterfly: name: 岳泽霖 age: 26 description: 一个孤独的小孩子
进行测试
可以打印出用户自定义输入的参数信息。
说明 自定义 Starter 是生效的。