Java 開發(fā)中,你真的了解這些對象的差異與用途嗎?
1. JavaBean
依據(jù)維基百科的闡述,JavaBean 通常是具備以下三種特性的公共 Java 類:
- 擁有無參構(gòu)造方法(默認構(gòu)造方法)。
- 所有屬性均為 private,外部需通過 public 的 getter 和 setter 方法訪問屬性。
- 實現(xiàn) Serializable 接口。
JavaBeans 規(guī)范指出,它是一種可在開發(fā)工具中可視化編輯的可重用軟件組件,包含一系列屬性與可能的事件。規(guī)范第 7 章規(guī)定其屬性應(yīng)為 private,外部通過 public 的 getter 和 setter 訪問;第 2 章規(guī)定需可序列化以便傳輸和持久化狀態(tài),但未要求必須有無參構(gòu)造方法。該規(guī)范于 1997 年發(fā)布,主要圍繞 Java Applet 設(shè)計,其 GUI 組件有屬性和事件且需可序列化,但在純服務(wù)器端開發(fā)中,部分對象不適用此定義,如數(shù)據(jù)庫連接或業(yè)務(wù)邏輯對象可能無需在電腦間傳輸,至少不適用可序列化特性。
2. EJB
EJB 是企業(yè)級 JavaBeans(Enterprise JavaBeans)的縮寫。根據(jù) EJB 規(guī)范,企業(yè)級 Bean 具有以下特性:
- 通常包含操作企業(yè)數(shù)據(jù)的業(yè)務(wù)邏輯。
- 由容器在運行時管理。
- 用戶需通過容器訪問。
- 能在部署時根據(jù)運行環(huán)境定制。
- 可通過注解或 XML 在編譯或部署時指定配置信息(可配置)。
- 僅使用 EJB 規(guī)范規(guī)定服務(wù)的企業(yè)級 Bean 可在任意 EJB 容器中使用(可移植)。
- 企業(yè)級 Bean 無需重新編譯即可封裝在企業(yè)應(yīng)用中。
此外,企業(yè)級 Bean 可以是有狀態(tài)或無狀態(tài)的,能實現(xiàn)業(yè)務(wù)邏輯或代表持久化實體,與 JavaBean 有較大區(qū)別,不一定是 JavaBean,也不一定有無參構(gòu)造方法和實現(xiàn) Serializable 接口。同時,規(guī)范雖未規(guī)定屬性必須為 private 及通過 public 的 getter 和 setter 訪問,但基于類的封裝性和降低耦合考慮,通常會遵循此設(shè)計。
3. Spring Bean
根據(jù) Spring Framework 官方文檔,在 Spring 中由 Spring IoC 容器管理且構(gòu)成應(yīng)用主干的對象即為 bean(IoC 是控制反轉(zhuǎn) Inverse of Control 的縮寫)。Spring beans 由 Spring IoC 容器依據(jù) XML 配置文件或注解等方式進行實例化、組裝和管理。它與 EJB 類似,通常包括數(shù)據(jù)庫連接、事務(wù)管理器等,區(qū)別在于 Spring beans 由 Spring IoC 容器管理,而 EJB 由 EJB 容器管理,且 Spring beans 同樣不一定有無參構(gòu)造方法和實現(xiàn) Serializable 接口。
4. POJO
POJO 是簡單的傳統(tǒng) Java 對象(Plain Old Java Object)的縮寫,也有其他類似說法,由 Martin Fowler 等人提出。結(jié)合 Spring 文檔,POJO 是盡量不依賴第三方庫、框架及 JavaEE 規(guī)范實現(xiàn)的 Java 對象,應(yīng)盡量不繼承類、不實現(xiàn)接口、不包含相關(guān)注解。它與 JavaBeans、EJB 和 Spring beans 無必然聯(lián)系,具有更高的可維護性和可移植性,開發(fā)人員可靈活選擇應(yīng)用場景,不受第三方庫或框架升級影響。
5. BO
BO 是業(yè)務(wù)對象(Business Object)的縮寫,用于描述業(yè)務(wù)邏輯中的對象且不依賴具體實現(xiàn)。其屬性應(yīng)與業(yè)務(wù)相關(guān)人員理解一致,例如用戶信息類中的字段命名應(yīng)符合業(yè)務(wù)人員認知。同時,一些特定情況下的對象不屬于 BO,如處理多對多關(guān)系的中間對象。通常 BO 在需求或設(shè)計中出現(xiàn),很少單獨編寫純粹的 BO 類,多作為其他對象的基類或組成部分。
6. DTO
DTO 是數(shù)據(jù)傳輸對象(Data Transfer Object)的縮寫,通常是 JavaBean(滿足無參構(gòu)造方法、private 屬性及對應(yīng) getter/setter、實現(xiàn) Serializable 接口),也通常是 POJO,以確保在交互系統(tǒng)間的可移植性。
7. PO
PO 是持久化對象(Persistent Object)的縮寫,與數(shù)據(jù)庫表及行對應(yīng),通常是 JavaBean,也可能包含 JPA 規(guī)范中的注解。在架構(gòu)設(shè)計中,PO 與 DTO 等對象應(yīng)區(qū)分開,因為數(shù)據(jù)庫對象有一些特定字段不應(yīng)暴露給用戶或其他系統(tǒng)。在 Hibernate 中,PO 有持久化對象狀態(tài)、值對象狀態(tài)和游離狀態(tài)三種狀態(tài),其狀態(tài)轉(zhuǎn)換與 Hibernate session 的操作相關(guān)。
8. VO
VO 有值對象(Value Object)和展現(xiàn)層對象(View Object)兩種含義。在 Hibernate 中,值對象是廣義 PO 的一種狀態(tài),除持久化和游離狀態(tài)的廣義 PO 外都是值對象;從另一定義看,用于存儲數(shù)據(jù)的對象如 PO 和 DTO 也可稱為值對象。展現(xiàn)層對象對應(yīng)客戶端頁面或組件中的數(shù)據(jù),與 DTO 結(jié)構(gòu)相似,用于業(yè)務(wù)邏輯層和客戶端頁面間傳輸數(shù)據(jù),二者是否合并可參考相關(guān)博文討論。
9. DO
DO 表示數(shù)據(jù)對象(Data Object)。阿里巴巴《Java 開發(fā)手冊》中的 DO 等同于 PO(一個 DO 類與一個數(shù)據(jù)庫表對應(yīng),一個 DO 與數(shù)據(jù)庫表中的一行對應(yīng)))。
10. DAO
DAO 是數(shù)據(jù)訪問對象(Data Access Object)的縮寫,封裝數(shù)據(jù)庫實現(xiàn)細節(jié)并抽象訪問方法,通常依賴注入容器注入數(shù)據(jù)庫連接對象等,所以通常是 EJB 或 Spring bean。
11. 總結(jié)
為了保持軟件工程的清晰結(jié)構(gòu)和部件功能的明確性,以及為了軟件的可擴展性、可移植性和可維護性,建議將這些不同類型的對象分別放置在不同的包中,避免混淆。雖然這樣做可能會增加初始開發(fā)的工作量,但從長遠來看,它有助于維護和擴展軟件系統(tǒng)。