如何创建自己的 Spring Boot 启动程序并为其编写单元测试
当我们想要封装一些自定义功能给别人使用的时候,创建Spring Boot Starter的形式是最好的实现方式。如果您还不会构建自己的Spring Boot Starter的话,本文将带你一起创建一个自己的Spring Boot Starter。
快速入门
-
创建一个新的 Maven 项目。第三方封装的命名格式是
xxx-spring-boot-starter
,例如:didispace-spring-boot-starter
。 -
编辑
pom.xml
,添加spring-boot-autoconfigure
和spring-boot-starter
依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
</dependencies>
- 创建一个用
@Configuration
注释的配置类,在这里您可以使用@Bean
来创建使用@ConditionalOnClass
、@ConditionalOnMissingBean
等条件注释来控制何时应用配置。
@Configuration
@ConditionalOnClass(MyFeature.class)
@ConditionalOnProperty(prefix = "myfeature", name = "enabled", matchIfMissing = true)
public class MyFeatureAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MyFeature myFeature() {
return new MyFeature();
}
}
- 在
src/main/resources/META-INF
目录下创建spring.factories
文件,并在org.springframework.boot.autoconfigure.EnableAutoConfiguration
关键字下列出您的自动配置类,比如:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.didispace.myfeature.MyFeatureAutoConfiguration
该配置的作用是让Spring Boot应用在引入您自定义Starter的时候可以自动这里的配置类。
注意:Spring Boot 2.7开始,不再推荐使用
spring.factories
,而是改用/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
,文件内容直接放需要自动加载配置类路径即可。这个变更具体可见之前的这篇文章:《Spring Boot 2.7开始spring.factories不推荐使用了》
验证测试
在制作Spring Boot Starter的时候,一定记得使用单元测试来验证和确保自动化配置类在任何条件逻辑在启动器下能够按照正确的预期运行。
创建单元测试
使用@SpringBootTest
加载完整的应用程序上下文,并验证启动程序是否正确配置了 Bean 和属性。
@SpringBootTest(classes = TestApplication.class)
public class MyStarterAutoConfigurationTest {
@Autowired(required = false)
private MyService myService;
@Test
public void testMyServiceAutoConfigured() {
assertNotNull(myService, "MyService should be auto-configured");
}
}
覆盖不同的配置
如果有不同的配置方案,那么还需要使用@TestPropertySource
或@DynamicPropertySource
覆盖属性以测试不同配置下的情况。
或者也可以直接简单的通过@SpringBootTest
中的属性来配置,比如下面这样:
@SpringBootTest(properties = "my.starter.custom-property=customValue")
public class MyStarterPropertiesTest {
@Value("${my.starter.custom-property}")
private String customProperty;
@Test
public void testPropertyOverride() {
assertEquals("customValue", customProperty, "Custom property should be overridden by @SpringBootTest");
}
}
覆盖@Conditional
的不同分支
如果您的启动器包含条件配置,比如:@ConditionalOnProperty
、@ConditionalOnClass
等注解,那么就必须编写测试来覆盖所有条件以验证是否已正确。
比如下面这样:
@SpringBootTest(classes = {TestApplication.class, MyConditionalConfiguration.class})
@ConditionalOnProperty(name = "my.starter.enable", havingValue = "true")
public class MyStarterConditionalTest {
@Autowired
private ApplicationContext context;
@Test
public void conditionalBeanNotLoadedWhenPropertyIsFalse() {
assertFalse(
context.containsBean("conditionalBean"),
"Conditional bean should not be loaded when 'my.starter.enable' is false"
);
}
}
为了覆盖不同的条件分支,我们通常还需要使用@TestConfiguration
注解来有选择地启用或禁用某些自动配置。
小结
本文介绍了两个Spring Boot的进阶内容:
- 如何创建 Spring Boot Starter
- 如何为 Spring Boot Starter 提供单元测试
掌握这项技能可以帮你更好的为Spring Boot提供模块划的功能封装。如果您学习过程中如遇困难?可以加入我们超高质量的Spring技术交流群,参与交流与讨论,更好的学习与进步!更多Spring Boot教程可以点击直达!,欢迎收藏与转发支持!
最后再给大家推荐一些有关Spring Boot Starter和自动化配置的扩展阅读:
- Spring Boot Starter配置spring.factories的自动生成神器
- Spring Boot自动化配置的利弊及解决之道
欢迎关注我的公众号:程序猿DD。第一时间了解前沿行业消息、分享深度技术干货、获取优质学习资源
推荐阅读
-
如何创建自己的 Spring Boot 启动程序并为其编写单元测试
-
玩转Java底层:JMX详解 - jconsole与自定义MBean监控工具的实际应用与区别" 在日常JVM调优中,我们熟知的jconsole工具通过JMX包装的bean以图形化形式展示管理数据,而像jstat和jmap这类内建监控工具则由JVM直接支持。本文将以jconsole为例,深入讲解其实质——基于JMX的MBean功能,包括可视化界面上的bean属性查看和操作调用。 MBeans在jconsole中的体现是那些可观察的组件属性和方法,如上图所示,通过名为"Verbose"的属性能看到其值为false,同时还能直接操作该bean的方法,例如"closeJerryMBean"。 尽管jconsole给我们提供了直观的可视化界面,但请注意,这里的MBean并非固定不变,开发者可根据JMX提供的接口将自己的自定义bean展示到jconsole。以下步骤展示了如何创建并注册一个名为"StudyJavaMBean"的自定义MBean: 1. 首先定义接口`StudyJavaMBean`,接口需遵循MBean规范,即后缀为"MBean"且包含getter方法代表属性,如`getApplicationName`,和无返回值的setter方法代表操作,如`closeJerryMBean`。 ```java public interface StudyJavaMBean { String getApplicationName(); void closeJerryMBean(); } ``` 2. 编写接口的实现类`StudyJavaMBeanImpl`,实现接口中的方法: ```java public class StudyJavaMBeanImpl implements StudyJavaMBean { @Override public String getApplicationName() { return "每天学Java"; } @Override public void closeJerryMBean() { System.out.println("关闭Jerry应用"); } } ``` 3. 在代码中注册自定义MBean,涉及的关键步骤包括: - 获取平台MBeanServer - 定义ObjectName,指定唯一的MBean标识符 - 注册MBean到服务器 - 启动RMI连接器服务,以便jconsole能够访问 ```java public void registerMBean() throws Exception { // ... 具体实现省略 ... } ``` 实际运行注册后的MBean,您将在jconsole中发现并查看自定义bean的属性和调用相关方法。然而,这种方式相较于传统的属性/日志查看和HTTP接口,实用性相对有限,可能存在潜在的安全风险。但不可否认的是,JMX及其MBean机制对于获取操作系统信息、内存状态等关键性能指标仍然具有重要价值。例如: 1. **获取操作系统信息**:通过JMX MBean,可以直接获取到诸如CPU使用率、操作系统版本等系统级信息,这对于资源管理和优化工作具有显著帮助。