Spring Modulith 1.3 有什麼新內容?

工程 | Oliver Drotbohm | 2024 年 11 月 22 日 | ...

經過半年的開發,Spring Modulith 1.3 GA已經發布。它充滿了新功能、改進,而且——最重要的是——社群貢獻。讓我帶你瞭解其中一些最有趣的內容。

基線升級

一如既往,Spring Modulith 的新次要版本會升級到最新的 Spring Boot 和 Spring Framework 版本,分別是3.46.2。即便如此,我們仍然相容它們的前代版本,以便你可以選擇性地升級到 Spring Modulith 1.3,而無需升級到最新的 Boot 和 Framework 版本。

應用程式模組模型

巢狀應用程式模組

Spring Modulith 的核心抽象在內部得到了顯著的改版,以支援一些很棒的新功能。一個應用程式模組現在可以包含巢狀的模組,這些模組對其他同級模組是隱藏的。這為組織應用程式提供了另一個層級的手段。巢狀應用程式模組是透過在由定義的檢測策略發現的模組的基礎包內巢狀的包上使用 Spring Modulith 的 @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

在這個例子中,inventory 是一個應用程式模組,如參考文件中所述。nested 包上的 @ApplicationModule 註解導致該包本身也成為一個巢狀的應用程式模組。在這種安排下,以下訪問規則適用:

  • Nested 中的程式碼只能從 InventoryInventory 內巢狀的同級應用程式模組公開的任何型別訪問。
  • Nested 模組中的任何程式碼都可以訪問父模組中的程式碼,包括內部程式碼。也就是說,NestedApiNestedInternal 都可以訪問 inventory.internal.SomethingInventoryInternal
  • 來自巢狀模組的程式碼也可以訪問頂級應用程式模組公開的型別。

nested (或任何子包) 中的任何程式碼都可以訪問 OrderManagement

外部應用程式模組

Spring Modulith 的預設應用程式模組檢測策略假設所有應用程式模組都位於相同的包名稱空間中。直到現在,向該安排中新增其他包只能透過提前知道要包含的包並在 @Modulithic(additionalPackages = "…" 中配置它們來實現。從 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(…) 變體轉換為 ApplicationModuleSource

整合測試

最佳化整合測試的執行一直是 Spring Modulith 的核心功能。應用程式模組可以使用 @ApplicationModuleTest 註解單獨或以不同程度的協作方式啟動。

在 1.3 版本中,我們透過 JUnit Jupiter 擴充套件擴充套件了此支援,該擴充套件將分析您應用程式所做的更改,並在測試執行時僅選擇真正需要執行的整合測試。預設情況下,我們考慮未提交的更改和您當前分支的跟蹤分支之上的提交。為了最佳化 CI 系統上的測試執行,可以為擴充套件提供一個提交雜湊——通常是最近一次成功構建的提交的雜湊——作為參考,以計算要考慮的更改檔案。

Some console output showing tests being skipped that would test functionality not affected by the current changes made to the repository

正如您所見,未受專案更改影響的測試已被跳過。非常感謝 Lukas DohmenDavid Bilge 對此功能的貢獻。

在整合測試支援方面,另一個微小但有用的新增功能是 @ApplicationModuleTest 現在可以透過其新引入的 module 屬性顯式定義要執行的模組。這使得整合測試可以位於應用程式模組的包空間之外,這也是由 Lukas 貢獻的。

事件釋出登錄檔

應用程式事件釋出模式

Spring Modulith 1.3 在其事件釋出支援方面提供了大量新功能。首先,我們提供了兩種新的完成模式,可以透過 spring.modulith.events.completion-mode 屬性進行配置。第一個新的完成模式 (delete) 會立即刪除已釋出的事件,而不是設定完成日期。這意味著登錄檔中的條目數量會保持較小,因此對於釋出大量事件的系統,效能開銷會更小。

立即刪除已完成的釋出存在無法訪問它們的缺點,例如用於統計目的。因此,我們還添加了一種歸檔 (archive) 模式,該模式維護一個專用的釋出歸檔,已完成的釋出將被移動到其中。這提供了相同的事件釋出效能改進,但將已完成的釋出單獨保留。

按識別符號完成事件釋出

直到現在,事件釋出都是透過裝飾事務性應用程式監聽器來完成的。這意味著完成程式碼只能訪問已消耗的原始應用程式事件和監聽器的識別符號,而不能訪問單個釋出的識別符號。

在 Spring Modulith 1.3 中,事件釋出登錄檔會跟蹤當前正在進行的事件釋出,從而允許我們發出引用釋出識別符號的釋出完成。這允許各個後端實現顯著提高完成操作的效能,因為索引可以使用得更有效。

更多資料庫和關係資料庫的模式支援

事件釋出登錄檔的 [關係資料庫後端] 現在支援另外三個資料庫,即 MariaDB、Oracle DB 和 Microsoft SQL Server。此外,可以為支援模式的資料庫定義用於 DDL 執行和常規操作的模式。

最後,spring.modulith.republish-outstanding-events-on-restart 已被棄用,取而代之的是新引入的 spring.modulith.events.republish-outstanding-events-on-restart,以保持一致性。

事件外部化

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 的訊息通道實現,因此您現在可以根據需要無縫地將應用程式事件輸入到其中。

將事件外部化到 Amazon SQS 和 SNS 的支援已移至 Spring Cloud for AWS 的當前版本(感謝 Maciej Walkowiak)。因此,我們正式棄用我們自己的實現,轉而支援他們的實現,這些實現是 Spring Modulith 原生實現的副本,應該是可以直接替換的。我們計劃在明年釋出的 2.0 版本中移除我們的工件。

文件支援

我們的文件支援也帶來了一些有趣的功能。首先,感謝 Cora Iberkleid,預設的文件生成過程會生成一個包含所有單獨建立的工件的聚合文件,方便預覽。每當您使用 DocumenterwriteDocumentation(…) 變體之一時,就會生成該文件。或者,在您選擇性地觸發生成單個圖和應用程式模組畫布後,顯式呼叫 writeAggregatingDocument(…)

畫布方便地佈局了構成其表面的應用程式模組的所有程式碼片段。我們一直透過整合第三方庫和相當複雜的構建設定,提供了此畫布包含 Javadoc(針對型別和方法,用於事件監聽器)的選項。在 1.3 版本中,我們現在提供了一個註解處理器(在 spring-modulith-apt 中),它可以自動將程式碼庫的 Javadoc 提取到可重用的 JSON 文件中,並且 Canvas 生成已更新為在存在時透明地使用該文件。它現在由 spring-modulith-starter-core 自動包含。

第三方整合

最後,為了方便起見,我們現在會自動觸發 [基於 ArchUnit] 的架構驗證(如果存在於類路徑上),例如 jMolecules 提供的關於 [Hexagonal、Onion 或分層架構] 的驗證。

獲取 Spring 新聞通訊

透過 Spring 新聞通訊保持聯絡

訂閱

領先一步

VMware 提供培訓和認證,助您加速進步。

瞭解更多

獲得支援

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案,只需一份簡單的訂閱。

瞭解更多

即將舉行的活動

檢視 Spring 社群所有即將舉行的活動。

檢視所有