中间件研发之Springboot自定义starter

Spring Boot Starter是一种简化Spring Boot应用开发的机制,它可以通过引入一些预定义的依赖和配置,让我们快速地集成某些功能模块,而无需繁琐地编写代码和配置文件。Spring Boot官方提供了很多常用的Starter,例如spring-boot-starter-web、spring-boot-starter-data-jpa等,但有时候我们也需要根据自己的业务需求,创建一些自定义的Starter,以便在不同的项目中复用一些通用的功能或组件。本文将以一个简单的日期格式化功能为例,介绍如何创建一个自定义的Spring Boot Starter,并说明其原理和使用方法。

一、Starter的命名规范

在创建一个自定义的Starter之前,我们需要先确定它的名称。Starter的命名有一种习惯,官方的Starter一般都是以spring-boot-starter-为前缀 ,后面跟上模块名,例如spring-boot-starter-web表示集成了Web开发相关的依赖和配置。而我们自定义的Starter一般都是以模块名为前缀,后面跟上-spring-boot-starter,例如data-spring-boot-starter表示集成了日期格式化相关的依赖和配置。这样做的目的是为了避免与官方或其他第三方提供的Starter产生冲突或混淆。

二、Starter项目的结构

创建一个自定义的Starter项目和创建一个普通的Spring Boot项目没有太大区别,我们可以使用IDE或者Spring Initializr来快速生成一个基本的项目结构。

一个典型的Starter项目结构如下:

data-spring-boot-starter

├── src

│ ├── main

│ │ ├── java

│ │ │ └── com.data.util

│ │ │ ├── autoconfigure // 自动配置类所在的包

│ │ │ │ ├── DataAutoConfiguration.java // 自动配置类

│ │ │ │ └── DataProperties.java // 属性类

│ │ │ └── util // 业务功能类所在的包

│ │ │ └──DataUtil.java // 业务功能类

│ │ └── resources

│ │ └── META-INF

│ │ └── spring.factories // Spring Boot自动装配文件

│ └── test

│ └── java

├── pom.xml // Maven依赖管理文件

└── README.md // 项目说明文档

三、Starter项目的依赖

在创建一个自定义的Starter项目时,我们需要在pom.xml文件中添加一些必要的依赖。首先,我们需要添加spring-boot-starter作为基础依赖 ,它提供了Spring Boot核心功能和默认配置。其次,我们需要添加spring-boot-configuration-processor作为编译时依赖,它可以帮助我们生成属性类和配置元数据,并且设置为可选依赖,避免传递给其他项目。最后,我们需要添加我们要集成的功能模块相关的依赖,例如在本例中,我们要集成日期格式化功能,所以我们不需要添加其他额外的依赖。以下是一个示例:

XML 复制代码
<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>

四、Starter项目的属性类

在创建一个自定义的Starter项目时,我们需要编写一个属性类,用来定义我们要集成的功能模块所需的配置项,并且使用@ConfigurationProperties注解来指定配置文件中的前缀。例如,在本例中,我们要集成日期格式化功能,所以我们需要定义一个日期格式的配置项,并且使用data作为配置文件中的前缀。以下是一个示例:

java 复制代码
package com.data.util.autoconfigure;
 
import org.springframework.boot.context.properties.ConfigurationProperties;
 
@ConfigurationProperties(prefix = "data")
public class DataProperties {
 
    private String pattern = "yyyy-MM-dd hh:mm:ss"; // 日期格式,默认为"yyyy-MM-dd hh:mm:ss"
 
    // 省略getter和setter方法
}

五、Starter项目的业务功能类

在创建一个自定义的Starter项目时,我们需要编写一个或多个业务功能类,用来实现我们要集成的功能模块的具体逻辑。例如,在本例中,我们要集成日期格式化功能,所以我们需要定义一个日期工具类,用来根据配置的日期格式将日期转换为字符串。以下是一个示例:

java 复制代码
package com.data.util.util;
 
import java.text.SimpleDateFormat;
import java.util.Date;
 
public class DataUtil {
 
    private String pattern; // 日期格式
 
    public DataUtil(String pattern) {
        this.pattern = pattern;
    }
 
    public String dateToStr(Date date){
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        String format = sdf.format(date);
        return format;
    }
}

六、Starter项目的自动配置类

在创建一个自定义的Starter项目时,我们需要编写一个自动配置类 ,用来根据属性类和业务功能类,创建相应的Bean对象,并且使用**@EnableConfigurationProperties注解** 来启用属性类,这个注解里面传入属性类的字节码文件。使用**@ConditionalOnClass注解** 来判断业务功能类是否存在,使用**@ConditionalOnProperty注解**来判断在对应的依赖了该Starter的SpringBoot配置文件中是否有相应的配置项。例如,在本例中,我们要集成日期格式化功能,所以我们需要根据DataProperties和DataUtil,创建一个DataUtil类型的Bean对象,并且使用data.enabled作为配置文件中的开关项。以下是一个示例:

java 复制代码
package com.data.util.autoconfigure;
 
import com.data.util.util.WoniuUtil;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
@Configuration
@EnableConfigurationProperties(DataProperties.class)
@ConditionalOnClass(DataUtil.class)
@ConditionalOnProperty(prefix = "data", name = "enabled", havingValue = "true")
public class DataAutoConfiguration {
 
    private final DataProperties dataProperties;
 
    public DataAutoConfiguration(DataProperties dataProperties) {
        this.dataProperties = dataProperties;
    }
 
    @Bean
    public DataUtil dataUtil() {
        return new DataUtil(dataProperties.getPattern());
    }
}

七、Starter项目的自动装配文件

在创建一个自定义的Starter项目时,我们需要在resources/META-INF目录下创建一个名为spring.factories的文件,用来指定我们的自动配置类,让Spring Boot能够在启动时自动扫描并加载它。以下是一个示例:

java 复制代码
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.data.util.autoconfigure.DataAutoConfiguration

八、Starter项目的使用方法

在完成了一个自定义的Starter项目后,我们可以将它打包成jar文件,并且发布到Maven仓库或者本地仓库,这样就可以在其他项目中引用它了。例如,在本例中,我们可以在其他项目的pom.xml文件中添加如下依赖:

XML 复制代码
<dependency>
    <groupId>com.data</groupId>
    <artifactId>data-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>

然后,在其他项目的配置文件中添加如下配置项:

XML 复制代码
data:
  enabled: true # 开启日期格式化功能
  pattern: yyyy-MM-dd # 设置日期格式,可选,默认为yyyy-MM-dd hh:mm:ss

最后,在其他项目的代码中,我们可以通过注入WoniuUtil类来调用日期格式化功能。例如:

java 复制代码
package com.example.demo;
 
import com.data.util.util.WoniuUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
 
import java.util.Date;
 
@RestController
public class DemoController {
 
    @Autowired
    private WoniuUtil woniuUtil;
 
    @GetMapping("/date")
    public String date() {
        Date date = new Date();
        String str = woniuUtil.dateToStr(date);
        return str;
    }
}

这样,我们就可以通过访问/date来获取格式化后的日期字符串了。

九、Starter项目的原理

Starter项目的核心原理是基于Spring Boot的自动装配机制,即根据类路径和配置文件中的条件,动态地创建和注入Bean对象到应用上下文中。Starter项目通过在resources/META-INF目录下创建一个名为spring.factories的文件,来指定自动配置类的全限定名,让Spring Boot在启动时能够扫描并加载它。自动配置类则通过一系列的注解来定义和控制自动装配的逻辑,例如:

  • @Configuration注解标识这是一个配置类,用来创建和注册Bean对象。
  • @EnableConfigurationProperties注解启用属性类,并将其注入到配置类中。
  • @ConditionalOnClass注解判断类路径中是否存在指定的类,如果存在则满足条件。
  • @ConditionalOnProperty注解判断配置文件中是否存在指定的属性,如果存在并且值与期望相符,则满足条件。
  • @Bean注解根据属性类和业务功能类,创建相应类型的Bean对象,并注册到应用上下文中。

当所有的条件都满足时,Starter项目就能实现自动装配的功能,让我们无需手动编写和配置Bean对象,只需引入依赖和设置属性即可。

相关推荐
Yan.love17 分钟前
开发场景中Java 集合的最佳选择
java·数据结构·链表
椰椰椰耶20 分钟前
【文档搜索引擎】搜索模块的完整实现
java·搜索引擎
大G哥20 分钟前
java提高正则处理效率
java·开发语言
智慧老师1 小时前
Spring基础分析13-Spring Security框架
java·后端·spring
lxyzcm1 小时前
C++23新特性解析:[[assume]]属性
java·c++·spring boot·c++23
V+zmm101341 小时前
基于微信小程序的乡村政务服务系统springboot+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm
Oneforlove_twoforjob2 小时前
【Java基础面试题025】什么是Java的Integer缓存池?
java·开发语言·缓存
xmh-sxh-13142 小时前
常用的缓存技术都有哪些
java
迷糊的『迷』2 小时前
vue-axios+springboot实现文件流下载
vue.js·spring boot
AiFlutter2 小时前
Flutter-底部分享弹窗(showModalBottomSheet)
java·前端·flutter