簡體   English   中英

為了避免XMLEncoder的序列化,你如何在Javabean中將屬性標記為瞬態?

[英]How do you mark a property as transient in a Javabean in order to avoid serialization by XMLEncoder?

在變量聲明上使用“transient”關鍵字或在getter上使用“@Transient”不會阻止XMLEncoder序列化屬性。 我發現告訴XMLEncoder不要序列化特定屬性的唯一方法是使用以下代碼:

BeanInfo info = Introspector.getBeanInfo(MyClass2.class);
PropertyDescriptor[] propertyDescriptors = info.getPropertyDescriptors();
for (int i = 0; i < propertyDescriptors.length; ++i) {
    PropertyDescriptor pd = propertyDescriptors[i];
    if (pd.getName().equals("props")) {
        pd.setValue("transient", Boolean.TRUE);
    }
}

真??? 是否有一種更簡單的方法,不需要運行時代碼循環遍歷所有屬性? 類似於瞬態修改器的東西會晃動!

這是一個JavaBean,它將具有由XMLEncoder序列化的所有屬性,盡管使用了“transient”:

import java.io.Serializable;
import java.beans.XMLEncoder;

public class TestJavaBeanSerialization implements Serializable {
    public TestJavaBeanSerialization() {}
    private transient String myProp1 = null;
    private String myProp2 = null;
    @Transient public String getMyProp1() { return myProp1; }
    public void setMyProp1(String a) { myProp1 = a; }
    public String getMyProp2() { return myProp2; }
    public void setMyProp2(String a) { myProp2 = a; }

    public static void main( String[] args ) {
        TestJavaBeanSerialization myObj = new TestJavaBeanSerialization();
        myObj.setMyProp1("prop 1");
        myObj.setMyProp2("prop 2");
        XMLEncoder encoder = new XMLEncoder(System.out);
        encoder.writeObject(myObj);
        encoder.close();        
    }

}

這是運行該程序的輸出:

<?xml version="1.0" encoding="UTF-8"?> 
<java version="1.6.0_29" class="java.beans.XMLDecoder"> 
 <object class="TestJavaBeanSerialization"> 
  <void property="myProp1"> 
   <string>prop 1</string> 
  </void> 
  <void property="myProp2"> 
   <string>prop 2</string> 
  </void> 
 </object> 
</java> 

UPDATE

我還沒有收到原始問題的明確答案。 這篇文章是人們不斷引用的,但是它並不清楚,也沒有人給出API或規范的參考,明確指出將屬性標記為瞬態的唯一方法是遍歷所有屬性並調用“setValue”。

你使用錯誤的@Transient

應該使用java.beans.Transient作為注釋。 javax.persistence.Transient僅在數據庫持久性的上下文中受到尊重,而不是BeanInfo序列化。

解決方法可能是使用JAXB作為與Java 1.6捆綁在一起的XML序列化程序。 它支持@XmlTransient注釋。

我遇到了類似的問題,我正在尋找一個更簡單的解決方案。 我管理它的方式是打破Java Beans慣例。

如果您不想序列化字段,請不要為其設置getter setter。 而不是“獲取”和“設置”,使用其他前綴,如“檢索”和“保存”。 例如 -

int x=0;
public int retrieveX() {
    return x;
}
public void saveX(int x) {
    this.x = x;
}

這對我來說很有用,我肯定會幫助那些在代碼中沒有特別需要Java Beans約定的人。 使用這種方式可以在整個應用程序中使用該變量,但同時將其隱藏在XMLEncoder序列化程序中。

希望它將來有助於某人。

我習慣於在我自己的代碼中使用這個已知的解決方案多年,但是自Java 1.7以來有一個更簡單的解決方案java.beans.Transient注釋 請注意,您可以在getter和setter上使用它,但不能在javax.persistence.Transient (JPA)上的字段上使用它。

import java.beans.Transient;
import java.beans.XMLEncoder;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Arrays;

public class Test {

public static final void main(String[] args) throws Throwable {
    final Capsule caps = new Capsule();
    caps.setIdentifier("6545346");
    caps.setMe("Julien");
    caps.setSentences(new ArrayList<>(Arrays.asList(new String[]{"I don't like my job","I prefer sleeping"})));
    try (FileOutputStream fOut = new FileOutputStream(new File(System.getProperty("user.home"), "test.xml")); 
         BufferedOutputStream out = new BufferedOutputStream(fOut);
         XMLEncoder encoder = new XMLEncoder(out)) {
        encoder.writeObject(caps);
        encoder.flush();
    }
}

public static final class Capsule {

    private String identifier;

    private transient String me;

    private transient ArrayList<String> sentences;

    public Capsule() {
        super();
    }

    @Transient
    public ArrayList<String> getSentences() {
        return sentences;
    }

    @Transient
    public void setSentences(ArrayList<String> sentences) {
        this.sentences = sentences;
    }

    public String getIdentifier() {
        return identifier;
    }

    public void setIdentifier(String identifier) {
        this.identifier = identifier;
    }

    @Transient
    public String getMe() {
        return me;
    }

    @Transient
    public void setMe(String me) {
        this.me = me;
    }
}}

結果是:

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_76" class="java.beans.XMLDecoder">
 <object class="Test$Capsule">
  <void property="identifier">
   <string>6545346</string>
  </void>
 </object>
</java>

注意沒有瞬態值。 我無法在2009年跳過這些收藏,但它現在似乎有效。

這是聲明屬性是瞬態的唯一方法。您可以看到該文章。 網址是http://www.oracle.com/technetwork/java/persistence4-140124.html?ssSourceSiteId=otncn#transient

myProp1字段添加靜態,並在getMyProp1方法之前刪除'@Transient'關鍵字,然后運行程序,結果是你想要的?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM