一、引言
DO、DTO、BO、AO、VO、POJO的概念看似簡單,但是想區分好或者理解好也不容易,本文簡單梳理一下。通過各層POJO的使用,有助於提高代碼的可讀性和可維護性。
二、區別
《阿里巴巴Java開發規范》關於領域模型的部分介紹如下:
分層領域模型規約: DO(Data Object):此對象與數據庫表結構一一對應,通過 DAO 層向上傳輸數據源對象。 DTO(Data Transfer Object):數據傳輸對象,Service 或 Manager 向外傳輸的對象。 BO(Business Object):業務對象,由 Service 層輸出的封裝業務邏輯的對象。 AO(ApplicationObject):應用對象,在Web層與Service層之間抽象的復用對象模型, 極為貼近展示層,復用度不高。 VO(View Object):顯示層對象,通常是 Web 向模板渲染引擎層傳輸的對象。 Query:數據查詢對象,各層接收上層的查詢請求。注意超過 2 個參數的查詢封裝,禁止 使用 Map 類來傳輸。
最難理解的是BO,大致這么理解:
BO這個對象可以包括一個或多個其它的對象。
比如一個簡歷,有教育經歷、工作經歷、社會關系等等。
我們可以把教育經歷對應一個PO,工作經歷對應一個PO,社會關系對應一個PO。
建立一個對應簡歷的BO對象處理簡歷,每個BO包含這些PO。這樣處理業務邏輯時,我們就可以針對BO去處理。
------------------------------------------------------------------------------------------------------------------------------------------------------
大致的示例代碼:
1) Controller層
public List<UserVO> getUsers(UserQuery userQuery);
此層常見的轉換為:DTO轉VO
2) Service層、Manager層
// 普通的service層接口
List<UserDTO> getUsers(UserQuery userQuery);
然后在Service內部使用UserBO封裝中間所需的邏輯對象
// 來自前端的請求
List<UserDTO> getUsers(UserAO userAo);
此層常見的轉換為:DO轉BO、BO轉DTO
3) DAO層
List<UserDO> getUsers(UserQuery userQuery);
三、各種對象該怎么轉換?
那么這里又涉及到另外一個問題,各種對象轉換該怎么辦呢?常見的寫一個轉換方法,然后手動調用get/set方法,屬性太多非常痛苦,容易遺漏或者重復,而且效率非常低下。
推薦兩種方式:
1)通過IDEA插件實現快速自動生成轉換代碼。如Generate All setters插件,參見 超實用的IDEA插件推薦,定義好參數和返回值,使用快捷方式可以輕松生成轉換的代碼。
2)通過第三方轉換庫來轉換。
- Apache org.apache.commons.beanutils.PropertyUtils.copyProperties
- Apache org.apache.commons.beanutils.BeanUtils.copyProperties
- Spring org.springframework.beans.BeanUtils.copyProperties
- Cglib BeanCopier
- Dozer
- orika
對應的maven依賴(已經給出了maven地址,建議用最新版本)
<!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils --> <dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId> <version>1.9.3</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>5.1.6.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/cglib/cglib --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.2.11</version> </dependency> <!-- https://mvnrepository.com/artifact/net.sf.dozer/dozer --> <dependency> <groupId>net.sf.dozer</groupId> <artifactId>dozer</artifactId> <version>5.5.1</version> </dependency> <!-- https://mvnrepository.com/artifact/ma.glasnost.orika/orika-core --> <dependency> <groupId>ma.glasnost.orika</groupId> <artifactId>orika-core</artifactId> <version>1.5.4</version> </dependency>
從效率來講,讀過其他文章,綜合而言cglib應該最高,其次是orika。因為cglib用的是asm,直接操作內存對象的字節碼增強技術。orika用的是javassist,通過動態字節碼生成實現對象轉換。
具體用法在這里就不介紹了,需要的話去官網看看文檔也可以去github看下demo。
我的看法:
第二種代碼實現對象轉換簡潔並且功能強大,但是我個人非常推崇第一種寫轉換方法的方式,因為這種方式對象屬性改變可以直觀反映到代碼上,也可以避免因為粗心和增刪屬性等出現的莫名其妙的錯誤。
————————————————
版權聲明:本文為CSDN博主「明明如月學長」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/w605283073/article/details/89715188