日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

JavaBean 持久化

發布時間:2023/12/3 java 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JavaBean 持久化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【0】README

0.1)本文文字描述轉自 core java volume 2,旨在學習 ?JavaBean 持久化 的基礎知識;

0.2)本文所有源代碼荔枝均為原創;

0.3) for complete souce code, please visit ?https://github.com/pacosonTang/core-java-volume/tree/master/coreJavaAdvanced/chapter8

--------------------------------------------------------------------------------------------------------------

【1】JavaBean 持久化

1)JavaBena持久化定義:?用JavaBean的屬性來將 bean 存儲到流中, 并在之后的某個時刻,或者在另一個虛擬機中再將它們讀回來;(javabean持久化定義) 2)JavaBean持久化與對象序列化的區別:?JavaBean 持久化適合于長期存儲; 3)problem+solution: 3.1)problem:序列化不適合長期存儲; 3.2)solution:人們發明了長期存儲機制——JavaBean持久化技術。 4)JavaBean持久化背后的思想: 4.1)對象序列化:假設你想將一個 JFrame 對象保存到一個文件中,以便以后可以讀取。如果看一看JFrame 的源碼會發現它有幾十個實例域。如果該類被序列化,那么所有這些域的值都需要被寫下來。 4.1.1)看看窗體(JFrame)是如何構造的: JFrame frame = new JFrame(); frame.setTitle("my app"); frame.setVisible(true); 默認的無參構造器會初始化所有的實例域,然后由你設置一兩個屬性。然而,?如果該類被序列化,那么所有這些域的值都需要被寫下來。(干貨——序列化存儲類的缺點是太冗余了,因為它要把所有域都保存下來) 4.2)如果用JavaBean持久化來保存的話,會產生如下XML語句: <object class="javax.swing.JFrame"><void property="title"><string>my app</string></void><void property="visible"><boolean>true</boolean></void> </object> 4.2.1)當該對象被讀回的時候,只需要加載上述XML文件; Attention)?JavaBean持久化只會保存那些與默認值不同的屬性。這個過程叫做——消除冗余;(干貨——消除冗余定義) 5)XMLEncoder + XMLDecoder: 5.1)要將對象保存為流,需要使用 XMLEncoder: XMLEncoder out = new XMLEncoder(new FileOutputStream(...)); out.writeObject(); out.close(); 5.2)從文件中讀取對象,需要使用 XMLDecoder: XMLDecoder in = new XMLDecoder(new FileInputStream(...)); JFrame frame = (JFrame)in.readObject(); in.close(); package com.corejava.chapter8;public class Hello {private String msg = "hello";private String speaker = "xiaotang";public String getMsg(){return msg;}public void setMsg(String msg){this.msg = msg;}public String getSpeaker(){return speaker;}public void setSpeaker(String speaker){this.speaker = speaker;} }package com.corejava.chapter8;import java.beans.XMLDecoder; import java.beans.XMLEncoder; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream;public class PersistentTest {public static void main(String[] args){XMLEncoder e = null;// 持久化 java類到 XMLtry{e = new XMLEncoder(new BufferedOutputStream(new FileOutputStream("com/corejava/chapter8/persistent.xml")));} catch (Exception ex){ex.printStackTrace();}Hello hello = new Hello();hello.setMsg("this is a test");hello.setSpeaker("persistent tang");e.writeObject(hello);e.close();// 持久化處理結束System.out.println("write Sucess");// 讀取持久化對象XMLDecoder d = null;try{d = new XMLDecoder(new BufferedInputStream(new FileInputStream("com/corejava/chapter8/persistent.xml")));} catch (Exception f){f.printStackTrace();}Object result = d.readObject();Hello test = (Hello) result;System.out.println(test.getMsg() + test.getSpeaker());// 讀取持久化對象結束} }<?xml version="1.0" encoding="UTF-8"?> <java version="1.8.0_60" class="java.beans.XMLDecoder"><object class="com.corejava.chapter8.Hello"><void property="msg"><string>this is a test</string></void><void property="speaker"><string>persistent tang</string></void></object> </java>


【2】 JavaBean持久化可用于任何數據 1)XMLEncoder 內置了對下列類型的支持:

null;

所有基本類型及其包裝器類型;

枚舉;(從 Java SE6 開始)

String;

數組;

集合與映射表;

反射類型 Class, Field, Method 和 Proxy;

AWT類型.....

AWT 和 Swing 構建, 邊界,布局管理器和模型;

事件處理器;


?【3】編寫一個持久化代理(Persistence Delegate) 來構造對象 2.1)problem+solution: 2.1.1)problem: ?如果可以通過屬性得到每個對象的狀態,那么使用 JavaBean持久化就是小菜一碟。但是,在真實的程序中,總有些類無法這樣工作。如一個沒有默認的無參構造器的Employee,它沒有 setName, setSalary, setHireDay方法; 2.1.2)solution:要克服這個問題,可以定義一個持久化代理,該代理負責生成對象的XML 編碼機制:(干貨——引入持久化代理) 2.2)Employee類的持久化代理覆寫了 instantiate 方法,以生成一個構造對象的表達式:? PersistenceDelegate delegate = new PersistenceDelegate(){protected Expression instantiate(Object oldInstance, Encoder out){Employee e = (Employee) oldInstance;GregorianCalendar c = new GregorianCalendar();c.setTime(e.getHireDay());return new Expression(oldInstance, Employee.class, "new", new Object[] {e.getName(), e.getSalary(), c.get(Calendar.YEAR), c.get(Calendar.MONTH),c.get(Calendar.DATE) });}}; 對以上代碼的分析(Analysis):?要重新生成oldInstance, 可以調用 Employee.class 對象上的new 方法(也就是構造器), 并提供指定的參數。? 3)安裝持久化代理有兩種選擇: 3.1)一種是將其與某個具體的 XMLWriter 相關聯: out.setPersistenceDelegate(Employee.class, delegate); 3.2)或者,可以設置 Beaninfo 的 bena 描述符的 persistenceDelegate 屬性: BeanInfo info = Introspector.getBeanInfo(GregorianCalendar.class); info.getBeanDescriptor().setValue("persistenceDelegate", delegate); 3.3)一旦安裝了代理, 就可以保存Employee 對象了,如: Object myData = new Employee("harry hacker", 50000, 1989, 10, 1); 4) 持久化代理構造對象的荔枝
package com.corejava.chapter8;import java.beans.DefaultPersistenceDelegate; import java.beans.Encoder; import java.beans.Expression; import java.beans.PersistenceDelegate; import java.beans.XMLEncoder; import java.io.BufferedOutputStream; import java.io.FileOutputStream;public class PersistentDelegateTest {public static void main(String[] args){// 持久化代理對象PersistenceDelegate delegate = new DefaultPersistenceDelegate(){protected Expression instantiate(Object oldInstance, Encoder out){Employee e = (Employee) oldInstance;return new Expression(oldInstance, Employee.class, "new", new Object[]{e.getName(),e.getSalary(),e.getAge()});}};XMLEncoder out = null;// 持久化 java類到 XMLtry{out = new XMLEncoder(new BufferedOutputStream(new FileOutputStream("com/corejava/chapter8/persistent_delegate.xml")));} catch (Exception ex){ex.printStackTrace();}// 安裝持久化代理對象out.setPersistenceDelegate(Employee.class, delegate);Employee employee = new Employee("xiao tang", 110, 25);out.writeObject(employee);out.close();// 持久化處理結束System.out.println("write Sucess");} } package com.corejava.chapter8;// <span style="color:#ff0000;"><strong>無設置器(setXXX方法),也沒有默認構造器</strong></span> public class Employee {private String name;private double salary;private int age;public Employee(String name, double salary, int age){this.name = name;this.salary = salary;this.age = age;}public String getName(){return name;}public double getSalary(){return salary;}public int getAge(){return age;} } <?xml version="1.0" encoding="UTF-8"?> <java version="1.8.0_60" class="java.beans.XMLDecoder"><object class="com.corejava.chapter8.Employee"><string>xiao tang</string><double>110.0</double><int>25</int></object> </java>
【4】由屬性構造對象 4.1)如果構造器所需的參數都可以通過訪問 oldInstance 的屬性獲得, 那你就不必自己編寫 instantiate 方法了。?你可以直接構造一個 ?DefaultPersistenceDelegate, 然后提供屬性的名字即可。 4.2)看個荔枝:下面的語句為 Rectangle2D.Double 類設置了持久化代理: out.setPersistenceDelegate(Rectangle2D.Double.class, new DefaultPersistenceDelegate(new String[]{"x", "y", "width", "height"})); 對上述代碼的分析(Analysis): A1)它告訴編譯器:?“要編碼一個 Rectangle2D.Double 對象, 就要取得它的 x, y, width 和 height屬性”, 并且用它們來調用構造器。其結果會產生包含如下元素的輸出: <object class="java.awt.geom.Rectangle2DDouble"><double>5.0</double><double>10.0</double><double>20.0</double><double>30.0</double> </object> 5)使用@ConstructorProperties注解構造器: 5.1)看個荔枝:?假設Employee 類有一個接收3個參數的構造器,我們對其進行注解:?? @ConstructorProperties({"name","salary","age"}) public Employee(String name, double salary, int age) 對上述代碼的分析(Analysis): A1)?這可以告訴編碼器去調用 getName, getSalary ?和 getHireDay 這三個屬性獲取方法, 并將得到的值寫入 object 表達式; A2)?@ConstructorProperties 注解是在 Java SE6 中引入的,因此只在 java 管理擴展(JMX) API中得到了應用; public class DefaultPersistentDelegateTest {public static void main(String[] args){XMLEncoder out = null;// 持久化 java類到 XMLtry{out = new XMLEncoder(new BufferedOutputStream(new FileOutputStream("com/corejava/chapter8/default_persistent_delegate.xml")));} catch (Exception ex){ex.printStackTrace();}// 安裝持久化代理對象// 它告訴編譯器: “要編碼一個 Employee 對象, // 就要取得它的 name, salary, age 屬性”, 并且用它們來調用構造器。out.setPersistenceDelegate(Employee.class, new DefaultPersistenceDelegate(new String[]{"name","salary","age"}));Employee employee = new Employee("default xiao tang", 110, 25);out.writeObject(employee);out.close();// 持久化處理結束System.out.println("DefaultPersistentDelegateTest write Sucess");} }
---------------------------------------------------------------------------------------------------------
【5】 使用工廠方法構造對象
5.1)
有時,你需要保存那些通過工廠方法獲得的對象,而不是通過構造器產生的對象。
5.2)看個荔枝:?思考 你是如何得到一個 InetAddress對象的:
byte[] bytes = new byte[] {127, 0, 0, 1}; InetAddress address = InetAddress.getByAddress(bytes);5.3) PersistenceDelegate 的 instantiate 方法會產生對工廠方法的一次調用:
protected Expression instantiate(Object oldInstance, Encoder out) { return new Expression(oldInstance, InetAddress.class, "getByAddress", new Object[] {((InetAddress)oldInstance).getAddress(); }); }5.4) 下面是一個輸出樣例:
<object class="java.net.Inet4Address" method="getByAddress"> <array class="byte" length="4"> <void index="0"> <byte>127</byte> </void> <void index="3"> <byte>1</byte> </void> </array> </object>
------------------------------------------------------------------------------------------------ 【6】構造后的工作
6.1)problem+solution:
6.1.1)problem:
某些類的狀態是通過調用 非屬性設置方法來建立的,即 非 setXXX方法;
6.1.2)solution: 你可以通過覆寫 DefaultPersistenceDelegate 的 initialize 方法來處理這種狀況。initialize 方法會在 instantiate 方法之后調用, 在其中你可以生成將被 記錄在bean存檔文件中的 語句序列;
6.2)看個荔枝: 為了重新生成一個 BitSet 對象,你要設置原對象中存在的所有位。下面的 initialize 方法生成了必要的語句:
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) { super.initialize(type, oldInstance, newInstance, out); BitSet bs = (BitSet) oldInstance; for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) out.writeStatement(new Statement(bs, "set", new Object[] { i, i + 1, true })); }6.2.1)輸出樣例如下所示:
<object class="java.util.BitSet"> <void method="set"> <int>1</int> <int>2</int> <boolean>true</boolean> </void> <void method="set"> <int>4</int> <int>5</int> <boolean>true</boolean> </void> </object>Attention) 編寫 new Statement(bs, "set", new Object[]{i}) 會更加有意義, 不過,那樣的話, XMLWriter 會使用一個空的名字來設置屬性, 而這樣的語句不是很直觀;
------------------------------------------------------------------------------------------------
【7】 瞬態屬性
7.1)problem+solution:
7.1.1)problem:
偶爾, 類中會包含能夠被 XMLDecoder 發現的帶有 getXXX 和 setXXX的屬性, 但是 你不希望在存檔文件中包含該屬性的值;
7.1.2)solution:為了禁止某個屬性被存檔, 可以在屬性描述符中將 它標記為 transient;(干貨——引入transient屬性標記)
7.2)看個荔枝:
下面的語句吧 DamageReporter 類的 removeMode屬性標記為 瞬時的;
BeanInfo info = Introspector.getBeanInfo(DamageReport.class); for(PropertyDescriptor desc : info.getPropertyDescriptors()) if(desc.getName().equals("removeMode")) desc.setValue("transient", Boolean.TRUE);JavaBean 持久化的存檔的總結(Conclusion):
C1)
適合長期存儲的;
C2)小而且快的;
C3)易于生成的;
C4)易于人們進行編輯的;
C5)是標準java 的一部分;??

總結

以上是生活随笔為你收集整理的JavaBean 持久化的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。