当前位置: 首页 > news >正文

多模块 Starter 最佳实践(强烈推荐!!!)

目录

一、背景

二、目录和示意图

1、多模块 Maven Starter 的工程结构示意图

2、Starter 使用示意图

3、可视化的多模块 Starter 依赖与 Bean 注入流程图

三、相关代码

1、父工程 my-feature-parent/pom.xml

2、核心模块 my-feature-core

2.1 pom.xml

2.2 核心类 RequestLogger.java

3、自动配置模块 my-feature-spring-boot-autoconfigure

3.1 pom.xml

3.2 RequestLoggerProperties.java

3.3 RequestLoggerAutoConfiguration.java

3.4 自动配置声明 AutoConfiguration.imports

3.5 IDE 配置提示 additional-spring-configuration-metadata.json

4、Starter 聚合模块 my-feature-spring-boot-starter

4.1 pom.xml

5、Demo 测试项目 demo-spring-boot-app

5.1 pom.xml

5.2 application.yml

5.3 Controller 示例 TestController.java

6、使用方法

6.1 在父工程目录执行

6.2 启动 demo-spring-boot-app

6.3 测试接口

6.4 控制台输出

四、总结


一、背景

前面的文章我介绍了单模块的 Spring Boot 项目 设计一个完整可用的 Spring Boot Starter来实现 Starter。本文主要介绍下多模块 Maven 工程来实现Starter。

其实你当然可以写一个 单模块的 Spring Boot 项目 来实现 Starter,
但为什么大多数公司 / 社区 Starter(包括 Spring 官方的 starter)都推荐 多模块 Maven 工程 呢?我来拆一下原因:

特性 / 维度单模块 Starter多模块 Maven Starter(推荐)
工程结构一个 Spring Boot 项目,逻辑 + 配置混在一起多模块:core(逻辑) + autoconfigure(自动配置) + starter(聚合依赖)
逻辑复用性核心逻辑与 Spring Boot 强绑定,不容易在非 Spring Boot 项目使用core 独立,既可以在 Spring Boot,也可在普通 Java 项目使用
依赖污染容易把不必要的 Spring Boot 依赖传递给用户项目core 不依赖 Spring Boot,autoconfigure 依赖可选,starter 聚合,用户依赖干净
扩展性扩展功能容易让 Starter 臃肿可以独立拆模块(比如 MyBatis 插件、Web 拦截器、监控适配)
测试方便性单元测试与集成测试混杂,调试复杂core 可以单元测试,autoconfigure 可以 Spring Boot 测试,demo 应用单独集成验证
与官方 Starter 一致性结构不一致,用户上手可能不熟悉模仿 Spring 官方模式,用户熟悉且规范化
开发复杂度简单,适合临时内部使用结构稍复杂,需要多模块管理,但更专业
IDE 支持测试和运行方便,但逻辑/配置混杂各模块清晰,IDE 可单独加载模块,更易管理依赖和提示

二、目录和示意图

1、多模块 Maven Starter 的工程结构示意图

my-feature-parent/                ← 父工程(可选,用于统一版本管理)├── pom.xmlmy-feature-core/                  ← 核心逻辑模块(不依赖 Spring Boot)├── pom.xml└── src/main/java/com/example/myfeature/core/└── RequestLogger.java      ← 核心逻辑类└── src/test/java/...            ← 核心逻辑单元测试my-feature-spring-boot-autoconfigure/   ← 自动配置模块├── pom.xml└── src/main/java/com/example/myfeature/autoconfigure/├── RequestLoggerProperties.java   ← 配置属性类└── RequestLoggerAutoConfiguration.java  ← 自动配置类└── src/main/resources/META-INF/├── spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports  ← 声明自动配置类└── additional-spring-configuration-metadata.json  ← IDE 配置提示补充my-feature-spring-boot-starter/   ← Starter 聚合模块(无源码)├── pom.xml└── (只声明依赖 core + autoconfigure)demo-spring-boot-app/             ← 测试 / 示例项目├── pom.xml└── src/main/java/com/example/demo/└── TestController.java       ← 注入 RequestLogger 测试使用└── src/main/resources/application.yml└── myfeature.logger.enable-body: true└── myfeature.logger.max-body-length: 500

说明

  1. core

    • 只放业务逻辑,独立于 Spring Boot,可复用。

    • 可单独写单元测试,不依赖 Spring Boot 启动。

  2. autoconfigure

    • 放自动配置类 + @ConfigurationProperties

    • 资源文件:

      • AutoConfiguration.imports → 声明自动装配类

      • additional-spring-configuration-metadata.json → 补充 IDE 提示

  3. starter

    • 聚合 core + autoconfigure,用户只需引依赖即可。

  4. demo-spring-boot-app

    • 用来测试 Starter 是否开箱即用

    • 配置 application.yml,注入 Bean 验证功能

优势

  • 职责清晰:逻辑、自动配置、依赖聚合分开

  • 依赖干净:core 不依赖 Spring Boot,starter 聚合而不污染用户项目

  • 扩展性强:以后新增插件、功能模块可以单独拆模块

  • IDE 支持友好:有 metadata 文件,配置项自动提示

2、Starter 使用示意图

业务项目├── pom.xml│   └── 引入 my-feature-spring-boot-starter├── application.yml│   └── myfeature.logger.enable-body: true│   └── myfeature.logger.max-body-length: 500└── src/main/java/com/example/demo/└── TestController.java└── @Autowired RequestLogger loggermy-feature-spring-boot-starter├── 依赖 core + autoconfiguremy-feature-core└── RequestLogger.java  ← 核心逻辑类my-feature-spring-boot-autoconfigure├── RequestLoggerProperties.java  ← 读取配置└── RequestLoggerAutoConfiguration.java  ← 自动装配 @Bean└── META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports└── com.example.myfeature.autoconfigure.RequestLoggerAutoConfigurationSpring Boot 启动流程:1. 扫描 classpath,读取 AutoConfiguration.imports2. 加载 RequestLoggerAutoConfiguration3. 创建 RequestLogger Bean,并注入 RequestLoggerProperties(读取 application.yml 配置)4. 业务项目中 @Autowired RequestLogger 成功注入

流程说明

  1. 引入 Startercore + autoconfigure 被依赖

  2. Spring Boot 启动 → 自动扫描 AutoConfiguration.imports 文件

  3. 加载自动配置类 → 根据 @ConfigurationProperties 绑定配置

  4. 创建 Bean → 业务代码中可以直接 @Autowired RequestLogger 使用

3、可视化的多模块 Starter 依赖与 Bean 注入流程图

┌─────────────────────────────┐
│       业务项目 (Spring Boot) │
│                             │
│  application.yml             │
│  ┌─────────────────────┐    │
│  │ myfeature.logger.*  │    │
│  │ enable-body: true   │    │
│  │ max-body-length:500 │    │
│  └─────────────────────┘    │
│                             │
│  TestController.java         │
│  ┌─────────────────────┐    │
│  │ @Autowired          │    │
│  │ RequestLogger       │◀────┐
│  └─────────────────────┘    │
└─────────────┬───────────────┘│▼
┌─────────────────────────────┐
│ my-feature-spring-boot-starter │
│  (聚合模块)                   │
│  ┌───────────────────────┐ │
│  │ 依赖 core + autoconfigure │
│  └───────────────────────┘ │
└─────────────┬───────────────┘│▼
┌─────────────────────────────┐
│ my-feature-core             │
│  RequestLogger.java         │
│  (核心逻辑类)             │
│  log(String body)           │
└─────────────┬───────────────┘│ 被自动配置类引用▼
┌─────────────────────────────┐
│ my-feature-spring-boot-autoconfigure │
│  RequestLoggerProperties.java        │
│    - @ConfigurationProperties       │
│    - 绑定 application.yml 配置      │
│  RequestLoggerAutoConfiguration.java│
│    - @Configuration                  │
│    - @EnableConfigurationProperties │
│    - @Bean + @ConditionalOnMissingBean │
│  META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports │
│    - 声明自动配置类                 │
│  additional-spring-configuration-metadata.json │
│    - IDE 自动提示                   │
└─────────────┬───────────────┘│ Spring Boot 启动扫描▼
┌─────────────────────────────┐
│ Spring Boot 容器              │
│  1. 扫描 AutoConfiguration.imports │
│  2. 加载 RequestLoggerAutoConfiguration │
│  3. 创建 RequestLogger Bean         │
│     并注入 RequestLoggerProperties  │
│  4. Bean 注入到 TestController      │
└─────────────────────────────┘│▼
┌─────────────────────────────┐
│ Controller 使用 RequestLogger │
│  logger.log(body)            │
│  输出日志                     │
└─────────────────────────────┘

流程说明

  • 业务项目

    • 只配置 application.yml

    • 使用 @Autowired 注入 Bean

  • starter

    • 聚合 core + autoconfigure

    • 无源码,仅依赖声明

  • core

    • 核心逻辑类,不依赖 Spring Boot

    • 可在非 Spring Boot 项目复用

  • autoconfigure

    • 自动配置类 + 配置属性类

    • AutoConfiguration.imports 声明自动加载

    • additional-spring-configuration-metadata.json 增强 IDE 提示

  • Spring Boot 容器

    • 扫描自动配置类

    • 创建 Bean 并注入配置属性

    • 注入到 Controller 使用

三、相关代码

1、父工程 my-feature-parent/pom.xml

<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.0http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>my-feature-parent</artifactId><version>1.0.0</version><packaging>pom</packaging><modules><module>my-feature-core</module><module>my-feature-spring-boot-autoconfigure</module><module>my-feature-spring-boot-starter</module><module>demo-spring-boot-app</module></modules><properties><java.version>17</java.version><spring.boot.version>3.3.5</spring.boot.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring.boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><pluginManagement><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring.boot.version}</version></plugin></plugins></pluginManagement></build>
</project>

2、核心模块 my-feature-core

2.1 pom.xml

<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><parent><groupId>com.example</groupId><artifactId>my-feature-parent</artifactId><version>1.0.0</version></parent><artifactId>my-feature-core</artifactId><dependencies><!-- 核心业务依赖 --></dependencies>
</project>

2.2 核心类 RequestLogger.java

package com.example.myfeature.core;/*** 核心逻辑类:记录请求日志* 核心模块不依赖 Spring Boot,任何 Java 项目都可复用*/
public class RequestLogger {// 是否记录请求体private final boolean enableBody;// 请求体最大长度,超过截断private final int maxBodyLength;/*** 构造方法* @param enableBody 是否启用请求体记录* @param maxBodyLength 请求体最大长度*/public RequestLogger(boolean enableBody, int maxBodyLength) {this.enableBody = enableBody;this.maxBodyLength = maxBodyLength;}/*** 打印请求体* @param body 请求内容*/public void log(String body) {if (!enableBody) {System.out.println("Request logged (body disabled)");return;}// 截断超过长度的内容String truncated = body.length() > maxBodyLength? body.substring(0, maxBodyLength) + "...": body;System.out.println("Request body: " + truncated);}
}

3、自动配置模块 my-feature-spring-boot-autoconfigure

3.1 pom.xml

<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><parent><groupId>com.example</groupId><artifactId>my-feature-parent</artifactId><version>1.0.0</version></parent><artifactId>my-feature-spring-boot-autoconfigure</artifactId><dependencies><dependency><groupId>com.example</groupId><artifactId>my-feature-core</artifactId><version>${project.version}</version></dependency><!-- Spring Boot自动配置支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId><optional>true</optional> <!-- 关键:标记为可选 --></dependency><!-- 配置元数据生成 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency></dependencies>
</project>

3.2 RequestLoggerProperties.java

package com.example.myfeature.autoconfigure;import org.springframework.boot.context.properties.ConfigurationProperties;/*** 配置属性类,用于绑定 application.yml 或 application.properties 中的配置** @ConfigurationProperties 注解说明:* - prefix="myfeature.logger" 表示绑定配置前缀*   例如:myfeature.logger.enable-body* - Spring Boot 会自动将配置注入到这个类的属性中*/
@ConfigurationProperties(prefix = "myfeature.logger")
public class RequestLoggerProperties {/*** 是否启用请求体记录*/private boolean enableBody = true;/*** 请求体最大长度*/private int maxBodyLength = 1000;// getter & setterpublic boolean isEnableBody() { return enableBody; }public void setEnableBody(boolean enableBody) { this.enableBody = enableBody; }public int getMaxBodyLength() { return maxBodyLength; }public void setMaxBodyLength(int maxBodyLength) { this.maxBodyLength = maxBodyLength; }
}

3.3 RequestLoggerAutoConfiguration.java

package com.example.myfeature.autoconfigure;import com.example.myfeature.core.RequestLogger;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** 自动配置类** @Configuration 注解说明:* - 表示这是一个 Spring 配置类** @EnableConfigurationProperties 注解说明:* - 激活并注册 @ConfigurationProperties 的 Bean* - 将 RequestLoggerProperties 注入到 Spring 容器*/
@Configuration
@EnableConfigurationProperties(RequestLoggerProperties.class)
public class RequestLoggerAutoConfiguration {/*** Bean 定义方法** @Bean 注解说明:* - 将方法返回的对象注册为 Spring 容器中的 Bean** @ConditionalOnMissingBean 注解说明:* - 如果容器中已有相同类型 Bean,则不创建* - 避免用户自己定义 Bean 时被覆盖*/@Bean@ConditionalOnMissingBeanpublic RequestLogger requestLogger(RequestLoggerProperties props) {// 从配置属性中获取参数return new RequestLogger(props.isEnableBody(), props.getMaxBodyLength());}
}

3.4 自动配置声明 AutoConfiguration.imports

路径:src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

内容:

com.example.myfeature.autoconfigure.RequestLoggerAutoConfiguration

3.5 IDE 配置提示 additional-spring-configuration-metadata.json

路径:src/main/resources/META-INF/additional-spring-configuration-metadata.json

内容:

{"properties": [{"name": "myfeature.logger.enable-body","type": "java.lang.Boolean","description": "Enable request body logging","defaultValue": true},{"name": "myfeature.logger.max-body-length","type": "java.lang.Integer","description": "Maximum length of request body to log","defaultValue": 1000}]
}
注解作用
@ConfigurationProperties(prefix="...")绑定配置文件属性到 Java 类
@EnableConfigurationProperties(...)激活 ConfigurationProperties,并注入容器
@Configuration声明这是一个 Spring 配置类
@Bean将方法返回对象注册为 Spring Bean
@ConditionalOnMissingBean如果容器已有相同类型 Bean,则不创建(用户可覆盖默认 Bean)

4、Starter 聚合模块 my-feature-spring-boot-starter

4.1 pom.xml

<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><parent><groupId>com.example</groupId><artifactId>my-feature-parent</artifactId><version>1.0.0</version></parent><artifactId>my-feature-spring-boot-starter</artifactId><dependencies><!-- 引入自动配置模块 --><dependency><groupId>com.example</groupId><artifactId>my-feature-spring-boot-autoconfigure</artifactId><version>${project.version}</version></dependency><!-- 必需依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency></dependencies>
</project>

注意:starter 本身不需要源码,只负责聚合依赖。

5、Demo 测试项目 demo-spring-boot-app

5.1 pom.xml

<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><parent><groupId>com.example</groupId><artifactId>my-feature-parent</artifactId><version>1.0.0</version></parent><artifactId>demo-spring-boot-app</artifactId><dependencies><dependency><groupId>com.example</groupId><artifactId>my-feature-spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies>
</project>

5.2 application.yml

myfeature:logger:enable-body: truemax-body-length: 500

5.3 Controller 示例 TestController.java

package com.example.demo;import com.example.myfeature.core.RequestLogger;
import org.springframework.web.bind.annotation.*;/*** 测试 Controller* 验证 Starter 是否正确注入 Bean*/
@RestController
@RequestMapping("/test")
public class TestController {// RequestLogger Bean 会被自动注入private final RequestLogger logger;public TestController(RequestLogger logger) {this.logger = logger;}/*** 测试接口:打印请求体*/@PostMappingpublic String log(@RequestBody String body) {logger.log(body);return "ok";}
}

6、使用方法

6.1 在父工程目录执行

mvn clean install

6.2 启动 demo-spring-boot-app

mvn spring-boot:run -pl demo-spring-boot-app

6.3 测试接口

curl -X POST http://localhost:8080/test -d "Hello Starter!"

6.4 控制台输出

Request body: Hello Starter!

四、总结

这个示例完全覆盖了:

  • 多模块结构(core / autoconfigure / starter / demo)

  • 自动配置 + properties + AutoConfiguration.imports

  • IDE 智能提示(additional-spring-configuration-metadata.json)

  • demo 项目测试

http://www.dtcms.com/a/352646.html

相关文章:

  • Quarkus OIDC 安全链路时序图
  • git换行行为差异简述;.editorconfig换行行为简述
  • 打工人日报#20250826
  • 【PS实战】制作hello标志设计:从选区到色彩填充的流程(大学作业)
  • springboot启动的时候,只打印logo,不打印其他的任何日志的原因
  • 【ElasticSearch】数据同步
  • 人形机器人的“奥运会“:宇树科技领跑,动捕技术成训练关键
  • git submodule的基本使用
  • 数据与端点安全 (Protect data and apps)
  • 利用 Python 爬虫按关键字搜索 1688 商品详情 API 返回值说明(代码示例)实战指南
  • 从零开始配置前端环境及必要软件安装
  • 技术总结:AArch64架构下Jenkins Agent(RPM容器编译节点)掉线问题分析与排查
  • 基于用户行为分析的精确营销系统
  • 【java并发编程】--cas和synchronized
  • openEuler Embedded 的 Yocto入门 : 2. 构建一个Hello,world!
  • PWM控制实现呼吸灯
  • 基于CentOS7:Linux服务器的初始化流程
  • 基于51单片机的指纹红外密码电子锁
  • 【Elasticsearch】k-NN 搜索深度解析:参数优化与分数过滤实践
  • Pascal使用TMediaPlayer播放MIDI文件时的错误
  • 红外遥控模块
  • 逻辑流图、作业图、执行图、物理图
  • 嵌入式软件移植
  • 【制作100个Unity游戏】从零开始构建类《月圆之夜》《杀戮尖塔》的卡牌游戏(附带项目源码)
  • Windows远程协助安全配置与使用限制
  • STM32G4 SVPWM VF开环强拖电机
  • 2026 届最新大数据专业毕设选题推荐,毕业设计题目汇总
  • 达索 Enovia 许可管理技术白皮书:机制解析与智能优化实践
  • 段式存储、页式存储、段页式存储:三种内存管理策略的演进与权衡
  • PyTorch生成式人工智能——PatchGAN详解与实现