POJO和JavaBean的區別

POJO(plain ordinary javaobject):“簡單普通Java對象”
①有一些屬性爲private
②針對每一個屬性定義getset方法接口
③沒有任何類繼承,也沒有實現任何接口,更沒有其他框架入侵的java對象
示例:

public class BasicInfoVo {

	private String orderId;
	
	private Integer uid;
	
	
	public String getOrderId() {
	    return orderId;
	}
	
	public void setOrderId(String orderId) {
	    this.orderId = orderId;
	}
	
	public Integer getUid() {
	    return uid;
	}
	
	public void setUid(Integer uid) {
	    this.uid = uid;
	}
}

JavaBean:是一種Java語言編寫的可重用的組件
①所有屬性爲private
②有一個無參構造器
③這個類屬性使用gettersetter來訪問,其他方法遵從標準命名規範
④這個類的接口是可序列化的,實現serializable接口
示例:

public class UserInfo implements java.io.Serializable{  
  
//實現serializable接口。  
	private static final long serialVersionUID = 1L;  
	  
	private String name;  
	private int age;  
	  
	//無參構造器  
	public UserInfo() {  
	      
	}  
	
	public String getName() {  
	    return name;  
	}  
	
	public void setName(String name) {  
	    this.name = name;  
	}  
	
	public int getAge() {  
	    return age;  
	}  
	
	public void setAge(int age) {  
	    this.age = age;  
	}  
	
	//javabean當中可以有其它的方法  
	public void userInfoPrint(){  
	    System.out.println("");  
	} 
 }  

區別:
POJO其實是比javabean更純淨的簡單類或接口。POJO嚴格地遵守簡單對象的概念,而一些JavaBean中往往會封裝一些簡單邏輯。
POJO主要用於數據的臨時傳遞,它只能裝載數據, 作爲數據存儲的載體,而不具有業務邏輯處理的能力。
Javabean雖然數據的獲取與POJO一樣,但是javabean當中可以有其它的方法。

備註:
Serializable接口屬於標誌接口,這個接口沒有任何的方法定義,它僅僅只是標記某個類能被序列化和反序列化。(接口不包含任何方法)
一、什麼是序列化?
【將對象的狀態信息轉換爲可以存儲或傳輸的形式的過程,在序列化期間,對象將其當前狀態寫入到臨時存儲區或持久性存儲區,之後,便可以通過從存儲區中讀取或反序列化對象的狀態信息,來重新創建該對象】
序列化將數據分解成字節流,以便存儲在文件中或在網絡上傳輸。
反序列化就是打開字節流並重構對象。
二、什麼情況下需要序列化?
【當我們需要把對象的狀態信息通過網絡進行傳輸,或者需要將對象的狀態信息持久化,以便將來使用時都需要把對象進行序列化】
三、Serializable主要用來支持兩種主要的特性:
1、JavaRMI(remote method invocation),RMI允許像在本機上一樣操作遠程機器上的對象,當發送消息給遠程對象時,就需要用到序列化機制來發送參數和接受返回值。
2、JavaJavaBeanBean的狀態信息通常是在設計時配置的,Bean的狀態信息必須被保存下來,以便當程序運行時能恢復這些狀態信息,這也需要序Serializable機制。

只需要瞭解被序列化的類需要實現 Serializable 接口,使用 ObjectInputStreamObjectOutputStream 進行對象的讀寫。
四、常出現的情景
1、兩個類A B代碼完全相同,試圖通過網絡傳遞對象數據,A 端將對象 C 序列化爲二進制數據再傳給 BB 反序列化得到 C。但一直反序列化不成功。

解決:虛擬機是否允許反序列化,不僅取決於類路徑和功能代碼是否一致,一個非常重要的一點是兩個類的序列化 ID 是否一致(就是 private static final long serialVersionUID = 1L)。雖然兩個類的功能代碼完全一致,但是序列化 ID 不同,他們無法相互序列化和反序列化。

序列化 ID 在 Eclipse 下提供了兩種生成策略,
(1)固定的 1L(一般這麼做。可以確保代碼一致時反序列化成功)

private static final long serialVersionUID = 1L;

(2)一個是隨機生成一個不重複的 long 類型數據(作用是:通過改變序列化 ID 可以用來限制某些用戶的使用。)
2、Facade外觀模式:
Client 端通過 Façade Object 纔可以與業務邏輯對象進行交互。而客戶端的 Façade Object 不能直接由 Client 生成,而是需要 Server 端生成,然後序列化後通過網絡將二進制對象數據傳給 ClientClient 負責反序列化得到 Façade 對象。

即 服務端(生成Facade object)序列化 ----->客戶端(反序列化,得到Facade對象,可用其與業務邏輯對象交互)

該模式可以使得 Client 端程序的使用需要服務器端的許可,同時 Client 端和服務器端的 Façade Object 類需要保持一致。當服務器端想要進行版本更新時,只要將服務器端的 Façade Object 類的序列化 ID 再次生成,當 Client 端反序列化 Façade Object 就會失敗,也就是強制 Client 端從服務器端獲取最新程序。

3、一個類實現了序列化,並且有其靜態變量。
但序列化保存的是對象的狀態,靜態變量屬於類的狀態,因此 序列化並不保存靜態變量。

4、父類的序列化與transient
父類不實現序列化,子類實現序列化,則將子類對象反序列化後輸出父類定義的某變量的數值,該變量數值與序列化時的數值不同。

原因:一個java對象的構造必須先有父對象,再有子對象,反序列化也是,父類沒有實現序列化,則虛擬機不會序列化父類。

解決:
a、父類也實現序列化
b、爲父類創造默認的無參的構造方法,在父類無參構造方法中對父類進行變量初始化。則反序列化時,構造父對象時只能調用父類無參構造函數爲默認父對象,如果不先在無參構造函數中初始化變量,則父類變量值都會是默認聲明值,如0,null

所以,使變量不被序列化的方法有:
a、Transient 關鍵字的作用是控制變量的序列化,在變量聲明前加上該關鍵字,可以阻止該變量被序列化到文件中,在被反序列化後,transient 變量的值被設爲初始值,如 int 型的是 0,對象型的是 null
b、可以將不需要被序列化的字段抽取出來放到父類中,子類實現序列化,父類不實現,則父類的字段數據將不會被序列化。

5、對敏感字段加密
服務端給客戶端發送序列化對象數據,並在序列化時進行加密,客戶端用解密密鑰,在反序列化時,對密碼讀取,保證了序列化對象的數據安全。

在序列化過程中,虛擬機會試圖調用對象類裏的 writeObjectreadObject 方法,進行用戶自定義的序列化和反序列化,如果沒有這樣的方法,則默認調用是 ObjectOutputStreamdefaultWriteObject 方法以及 ObjectInputStreamdefaultReadObject 方法。用戶自定義的 writeObjectreadObject 方法可以允許用戶控制序列化的過程,比如可以在序列化的過程中動態改變序列化的數值。基於這個原理,可以在實際應用中得到使用,用於敏感字段的加密工作。

RMI技術。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章