今天要學習的是領域服務。領域服務用於實現特定於某個領域的任務。領域服務並非相似於應用服務同樣,應用服務作的事協調領域之間的關係,領域服務則負責的是業務。那麼咱們就瞭解一下應用服務和領域服務之間的區別和關係。java
應用層經過應用服務接口來暴露系統的所有功能。在應用服務的實現中,它負責編排和轉發,它將要實現的功能委託給一個或多個領域對象來實現,它自己只負責處理業務用例的執行順序以及結果的拼裝。經過這樣一種方式,它隱藏了領域層的複雜性及其內部實現機制。數組
應用層相對來講是較「薄」的一層,除了定義應用服務以外,在該層咱們能夠向其餘系統發生基於事件的消息通知,還能夠用於建立郵件以發送給客戶,因此該層的主要功能就是與多個領域服務對接,將領域所需的參數組裝傳遞,以獲得結果,拼接結果展示出來。ide
什麼是領域服務呢?學習
領域服務是用來協調領域對象完成某個操做,用來處理業務邏輯的,它自己是一個行爲,因此是無狀態的。狀態由領域對象(具備狀態和行爲)保存。ui
當領域中的某個操做過程或轉換過程不是實體或值對象的職責時,咱們便應該將該操做放在一個單獨的接口(這個接口並不是指對外部開放的接口,而是內部調用的接口,簡單理解就是service層接口)中,即領域服務。請確保該服務和通用語言時一致的;而且保證它是無狀態的。code
這樣描述依然很抽象,那麼根據這段描述咱們能夠總結一下。對象
(1)「當領域中的某個操做過程或轉換過程不是實體或值對象的職責時」,咱們能夠理解爲,執行一個顯著的業務操做過程,不是實體或者值對象的職責,那說明所須要的結果並非能直接的出來的,而是通過一些列業務操做獲得的,因此領域服務是一個業務操做的過程。接口
(2)「應該將該操做放在一個單獨的接口中」,上面也講了,這個接口是對內部的一個接口,就是說每一種業務流程都須要單獨放在一個接口當中,獨立出來,以達到解耦的目的。事件
對內對外,對程序而言,事實上是從展示層調用應用層,應用層調用領域層,領域層或調用基礎實施層。get
通過以上兩點解釋,能夠得知,領域服務是以多個領域對象輸入(業務操做不只僅只對一個領域對象操做,好比登陸起碼要對用戶、權限兩個領域對象操做),返回一個通過業務流程獲得的結果。
領域服務屬於領域層,領域層就是較「胖」的一層,由於它實現了所有業務邏輯而且經過各類校驗手段保證業務正確性。
先考慮實體或值對像的建模,不適合,而後才使用領域服務。實體和值對像纔是最重要的DDD建模對象,若是反而首先使用領域服務,容易致使「貧血領域模型」。既然不適合直接在實體或值對像上建模,也基本說明不少時候涉及到多個實體或值對像。
對用戶進行認證
public class UserAuthenticationServiceImpl implements UserAuthenticationService { @Autowired private UserAuthenticationRepository userAuthenticationRepository; @Override public User authentication(Long userid, String username, String password) { if (userid == null && username == null && password == null) { throw BusinessException.builder().message("is null").build(); } User user = new User(); user = userAuthenticationRepository.getUserAuthentication(userid, username, password); if (user !== null && user.getActivate() != null) { User auser = new User(); auser = userAuthenticationRepository.authentication(user); if (auser != null && auser.getEnabled()) { return auser; } } else { return null; } } }
用戶在展示層進行認證操做,應用層肯定用戶是要作認證操做後,調用認證的領域服務,認證領域服務先對值判空,經過以後再查詢用戶信息,判斷用戶是不是一個可激活狀態,再調用基礎層的認證方法返回認證後的用戶信息,最後判斷用戶是否激活,是就返回用戶信息。
當應用服務中的邏輯趨於複雜時,咱們就要當心領域邏輯泄露到應用服務中去。而在使用領域服務時,咱們又要避免過分使用,由於會致使貧血領域模型。畢竟有些單一的操做更適合放到領域對象(實體和值對象)中去。 因此總結如下: