DDD/HexArch提示與技巧:使用ComponentScan將領域繫結到Spring上下文 - beyondxscratch
六邊形架構告訴我們,領域內不應該存在任何框架,以避免技術意外的複雜性,並且無需重新開發業務邏輯部分即可輕鬆遷移到新的結構框架(或主要版本)。這意味著當您使用Spring時,您不能依賴任何構造型註釋,例如域內的@Service或@Component。
因此,我們通常在Spring Configurations中使用bean工廠方法,並使用大量樣板程式碼來例項化域服務,儲存庫和存根,因為我們認為我們不能將ComponentScan 用於領域物件。
@Configuration public class DomainConfiguration { @Bean public RetrieveSanitaryGrades retrieveSanitaryGrades() { return new RetrieveSanitaryGrades(); } @Bean public SearchRestaurants restaurantsFinder(Restaurants restaurants, OpeningHours openingHours, RetrieveSanitaryGrades retrieveSanitaryGrades) { return new RestaurantsFinder(restaurants, openingHours, retrieveSanitaryGrades); } } |
本文將向您展示如何在不違反六邊形架構規則的情況下利用元件掃描與Koltin中的程式碼示例。如果您正在使用Java,請不要擔心,程式碼將大致相同,您將不得不調整一點語法。
Spring元件掃描查詢帶有Spring構造型的帶註釋類,以標識要在ApplicationContext中註冊的物件。因此,這些物件將不可避免地依賴於Spring Framework,這基本上是領域實現的一個問題。。為了擺脫這種限制,我們將使用六邊形體系結構使用的技巧來確保您的域永遠不會依賴於持久層,這就是:依賴性反轉。
訣竅很簡單,在域內建立描述性註釋,以識別要向ApplicationContext公開的物件 - 通常是DomainServices和Stubs。
import java.lang.annotation.Inherited @Retention(AnnotationRetention.RUNTIME) @Target(AnnotationTarget.CLASS) @Inherited annotation class DomainService @Retention(AnnotationRetention.RUNTIME) @Target(AnnotationTarget.CLASS) @Inherited annotation class Stub |
保留策略設定為RUNTIME 以允許Spring發現它們。使用其他策略時,註釋將在執行時被丟棄,這對我們的情況沒有幫助。您現在可以使用自定義註釋安全地註釋要公開的領域物件。
您還可以為其他DDD物件(如Aggregate,Entity,ValueType,Repository)建立描述性註釋,即使您沒有將它們公開給ApplicationContext也是如此。這是一個很棒的技術,可以讓人們進入領域驅動設計(使用一些javadoc,請參閱下面的示例),或者只是為了更好地瞭解您的業務及其建模方式。
這有時對於檢測程式碼評審中的一些錯誤很有用。就像包含實體的ValueType,帶有副作用的ValueType一樣......有時很難確定我們正在處理的物件的性質,尤其是在複雜豐富的業務領域。
/** * <p> * A DDD aggregate is a cluster of domain objects that is treated as a * single unit to ensure consistency across them. * </p> * * @see <a href= "https://martinfowler.com/bliki/DDD_Aggregate.html"> * Aggregates in Domain Driven Design * </a> */ public @interface Aggregate { } |
現在,我們將告訴Spring像對待那些物件@Service,@Component註解一樣,透過配置我們的自定義域註釋在基礎設施掃描。只需建立一個DomainConfiguration並註釋如下:
@Configuration @ComponentScan( // basePackageClasses = [Recommendation::class], includeFilters = [ComponentScan.Filter(type = FilterType.ANNOTATION, value = [DomainService::class, Stub::class])]) class DomainConfiguration |
請注意,ComponentScan預設情況下僅在SpringBootApplication包中查詢,包括其子包。因此,如果您的域不在此層次結構中,則需要指定一個基本包類,以識別域的根包(請參閱上面的註釋程式碼)。通常,我們在這裡使用主域聚合,因為常見的DDD約定鼓勵我們在他之後命名根域包。
您還可以使用basePackages並將包名稱作為String。但是這種做法是不鼓勵的,因為不能適應包重構。
這是這種方法的限制:
- 如果需要一些基於條件或基於配置檔案的bean構造,則必須切換回bean工廠。
- 主觀:有些人不喜歡註釋。
- 如果您使用的是Kotlin,對maven外掛開放的類現在可以擴充套件,因此它違反了開放式原則。
如果您想進一步使用Maven,Koltin和SpringBoot實現基於六邊形體系結構的應用程式,您可以檢視此儲存庫。
相關文章
- DDD-領域物件與領域服務物件
- DDD領域驅動設計:領域事件事件
- 領域本體與DDD的UL語言
- 運用領域模型——DDD模型
- 使用Spring Data JPA在更改實體時釋出DDD領域事件 - thorbenSpring事件ORB
- 使用Typescript實現DDD領域建模 - Matthew de NobregaTypeScript
- 在DDD中建立領域模型模型
- DDD領域驅動最全詳解(圖文全面總結)
- 行為驅動開發(BDD)如何與領域驅動設計(DDD)結合?
- DDD劃分領域、子域,核心域,支撐域的目的
- 領域驅動模型DDD(三)——使用Saga管理事務模型
- DDD領域驅動設計初探(5):AutoMapper使用APP
- DDD學習(二)—— 領域建模重要概念
- 淺談DDD(領域驅動設計)
- 淺談 DDD 領域驅動設計
- DDD+Javascript領域建模示例 -Alex LawrenceJavaScript
- DDD-領域驅動設計示例
- DDD領域驅動設計總結和C#程式碼示例C#
- 《實現領域驅動設計》筆記——領域、子域和限界上下文筆記
- 領域驅動模型DDD(二)——領域事件的訂閱/釋出實踐模型事件
- 領域驅動設計 (DDD) 簡介 - jannikwempe
- 領域驅動設計(DDD)入門&概要
- DDD理論學習系列(9)-- 領域事件事件
- 領域驅動設計DDD應用心得
- 領域驅動設計(DDD)實踐之路(二):事件驅動與CQRS事件
- DDD領域層與基礎設施層迴圈依賴問題
- 領域驅動設計(DDD)實踐之路(一)
- 領域驅動設計(DDD)高手養成記
- 領域驅動模型DDD(一)——服務拆分策略模型
- 分享我的:領域驅動設計(DDD)學習成果精簡總結
- DDD中限界上下文與通用語言的作用
- 如何在 .Net 7 中將 Query 繫結到陣列陣列
- 將OleDbDataAdapter繫結到Winform下的DataGrid (轉)APTORM
- dayatang/dddlib:DDD領域驅動設計庫
- 領域驅動設計(DDD:Domain-Driven Design)AI
- 領域模型驅動設計(DDD)之模型提煉模型
- 使用反射對繫結url引數到結構體反射結構體
- dataGridView繫結Dictionary |Dictionary繫結到DataGridViewView