Spring Modulith 1.3 有哪些新功能?

关于Spring Modulith 1.3版本的新特性介绍。以下是该版本的主要更新内容:

1、基线升级:
Spring Modulith 1.3升级到了Spring Boot 3.4和Spring Framework 6.2的最新版本,同时保持与之前版本的兼容性,允许用户选择性升级到Spring Modulith 1.3而不必升级到最新的Boot和Framework版本。

2、应用模块模型:

  • 支持嵌套应用模块,这些模块对同级模块隐藏,增加了应用结构的灵活性。
  • 通过在模块的基础包内嵌套的包上使用@ApplicationModule(或jMolecules的@Module)来声明嵌套应用模块。
 Example
└─ src/main/java
   |
   ├─ example
   |  └─ Application.java
   |
   |  -> Inventory
   |
   ├─ example.inventory
   |  ├─ InventoryManagement.java
   |  └─ SomethingInventoryInternal.java
   ├─ example.inventory.internal
   |  └─ SomethingInventoryInternal.java
   |
   |  -> Inventory > Nested
   |
   ├─ example.inventory.nested
   |  ├─ ☕ package-info.java // @ApplicationModule
   |  └─ NestedApi.java
   ├─ example.inventory.nested.internal
   |  └─ NestedInternal.java
   |
   |  -> Order
   |
   └─ example.order
      ├─ OrderManagement.java
      └─ SomethingOrderInternal.java


包上的注释导致其反过来成为嵌套的应用程序模块。在该安排中,适用以下访问规则:@ApplicationModulenested

  • Nested中(
    example.inventory.nested
    )的代码仅可从Inventory或嵌套在Inventory内的兄弟应用程序模块公开的任何类型中获得。
  • 嵌套模块中的任何代码都可以访问父模块中的代码,甚至是内部代码。即和都NestedApi可以NestedInternal访问inventory.internal.SomethingInventoryInternal。
  • 嵌套模块中的代码还可以通过顶级应用程序模块访问公开的类型。
nested(或任何子包)中的任何代码都可以访问OrderManagement。


3、外部应用模块:

  • 在 1.3 版中,引入了SPI ApplicationModuleSourceFactory,可以通过META-INF/spring.factories注册,用于声明根包扫描、显式应用模块基础包,并可选地自定义应用模块检测策略。
package example;

public class CustomApplicationModuleSourceFactory implements ApplicationModuleSourceFactory {

  @Override
  public List<String> getRootPackages() {
    return List.of("com.acme.toscan");
  }

  @Override
  public ApplicationModuleDetectionStrategy getApplicationModuleDetectionStrategy() {
    return ApplicationModuleDetectionStrategy.explicitlyAnnotated();
  }

  @Override
  public List<String> getModuleBasePackages() {
    return List.of(
"com.acme.module");
  }
}

上述示例将使用 com.acme.toscan 来检测其中明确声明的模块,并从 com.acme.module 中创建应用模块。 由此返回的包名随后将通过 ApplicationModuleDetectionStrategy 中暴露的相应 getApplicationModuleSource(...) 函数转换为 ApplicationModuleSources。

4、集成测试:
优化集成测试的执行一直是 Spring Modulith 的核心功能。应用程序模块可以单独引导,也可以使用@ApplicationModuleTest注释以不同程度的协作进行引导。

  • @ApplicationModuleTest注解现在支持通过其新引入的module属性显式定义要执行的模块。
  • 引入了JUnit Jupiter扩展,分析应用变更并仅执行真正需要执行的集成测试。

5、事件发布注册表:
引入了两种新的完成模式:delete和archive,分别用于删除和归档事件发布。

  1. 第一种新的完成模式 ( delete) 立即删除发布,而不是设置完成日期。这意味着注册表中的条目数量保持较小,因此在发布大量事件的系统中产生的性能开销较小。
  2. 完成后立即删除发布内容的缺点是无法访问它们,例如出于统计目的。这就是为什么我们还添加了存档 ( archive) 模式,该模式维护一个专用的发布存档,已完成的发布内容将移至该存档。这在事件发布上产生了相同的性能改进,但单独保留了已完成的发布内容。

按标识符完成事件发布:

  • 支持通过标识符完成事件发布,提高了性能。
到目前为止,事件发布是通过修饰事务应用程序侦听器来完成的。这意味着完成代码只能访问使用的原始应用程序事件和侦听器的标识符,而不能访问单个发布的标识符。

在 Spring Modulith 1.3 中,事件发布注册表会跟踪当前正在进行的事件发布,因此我们可以根据发布的标识符发布发布完成。这允许各个后备存储实现显著提高完成操作的性能,因为可以更有效地使用索引。

支持更多关系数据库和数据表结构:包括MariaDB、Oracle DB和Microsoft SQL Server。

事件外部化

  • 事件外部化支持增加了消息头和动态路由目标的SpEL表达式。
  • 支持将事件写入Spring的MessageChannel抽象。
Spring Modulith 支持将应用程序事件轻松外部化到其他系统中,同时还提供了许多新功能。 发送出去的消息现在可以获得与之相关的头信息。 为此,EventExternalizingConfiguration 现在提供了各种 headers(...) 方法,允许为一般事件或特定事件类型注册自定义提取器。

@Configuration
class MyConfiguration {

  @Bean
  EventExternalizingConfiguration config(SomeBean bean) {

    return EventExternalizingConfiguration.defaults(…)
        .headers(event -> Map.of("signature", bean.signMessage(event)))
        .build();
  }
}


为了动态计算外部化事件的路由目标,除了之前已经支持的动态路由键之外,@Externalized 现在还支持 SpEL 表达式来定义这些表达式。 我们的好朋友 Josh Long 提供了一个新的外部化适配器,用于将事件写入 Spring 的 MessageChannel 抽象。

Spring Integration 的消息通道实现了这一接口,因此您现在可以根据需要将应用程序事件无缝地输入到这些通道中。 对亚马逊 SQS 和 SNS 事件外部化的支持已被转移到当前发布的 Spring Cloud for AWS 中(感谢 Maciej Walkowiak 提供的支持)。

因此,我们正式放弃了自己的实现,转而使用它们,它们是 Spring Modulith 本机实现的副本,可以直接替换。 我们计划在明年发布 2.0 版本时移除我们的工件。


文档支持:

  • 默认文档生成过程现在产生一个聚合文档,包含所有创建的单独构件,方便预览。
  • 提供了自动提取代码库中Javadoc的注解处理器,并更新了画布生成以透明使用。

第三方集成:

  • 如果类路径上存在jMolecules提供的基于ArchUnit的架构验证,则会自动触发。

这些更新为Spring Modulith的用户带来了更多的灵活性和便利性,特别是在模块化、集成测试和事件处理方面。如果您需要更详细的信息或有其他问题,请随时告知。