PersistenceDelegate- persistent proxy class

java.beans.PersistenceDelegate – persistent proxy class, persistent delegate

Official Document Original Word 1:

  • The persistence agent can control all aspects of object persistence, including:
  • 1. Determine whether an instance can be mutated into another instance of the same class.
  • 2. Instantiate the object by calling a public constructor or public factory method.
  • 3. Perform object initialization.

According to the official meaning, the delegation class is responsible for: the initialization operation of the object, and the identity conversion operation after initialization (same class, conversion of different instances)

Official Document Original Word 2:

  • The PersistenceDelegate class is responsible for expressing the state of an instance of a given class in terms of methods in the class’s public API.
  • This persistence scheme, unlike traditional serialization schemes, requires a mock of the writeObject method that does not have a corresponding readObject method
  • The writeObject emulator encodes each instance according to its public API, there is no need to define a readObject emulator

According to the official meaning, the persistent proxy class implements persistence and no longer provides the ReadObject method.
In actual development, colleagues need to have serialization and deserialization operations (that is, the readObject and writeObject methods have both).

The persistent proxy class only provides four methods:

protected void initialize(class<?> type, Object oldInstance, Object newInstance, Encoder out) -- initialization
protected abstract Expression instantiate(Object oldInstance, Encoder out)
protected boolean mutatesTo(Object oldInstance, Object newInstance) -- Compares two instances for equality
void writeObject(Object oldInstance, Encoder out)

The specific code of the instantiate method:

 protected Expression instantiate(Object oldInstance, Encoder out) {
        int nArgs = constructor.length;
        Class<?> type = oldInstance.getClass();
        Object[] constructorArgs = new Object[nArgs];
        for(int i = 0; i < nArgs; i + + ) {
            try {
                Method method = findMethod(type, this.constructor[i]);
                constructorArgs[i] = MethodUtil.invoke(method, oldInstance, new Object[0]);
            }
            catch (Exception e) {
                out.getExceptionListener().exceptionThrown(e);
            }
        }
        return new Expression(oldInstance, oldInstance.getClass(), "new", constructorArgs);
    }

It can be seen that this method creates new instance objects based on the number of constructors: as many constructors as there are, as many new instances are created.
In actual development, there is no need to create so many instances. Therefore, the usual proxy agents are new handwritten proxy classes to reduce the minimum memory consumption.

public class Encoder

Object get(Object oldInstance)
ExceptionListener getExceptionListener() – Gets the exception handler for this stream.
PersistenceDelegate getPersistenceDelegate(class<?> type) -- Returns a persistence proxy of the given type.
Object remove(Object oldInstance) -- Removes the entry for this instance, returning the old entry.
void setExceptionListener(ExceptionListener exceptionListener) -- Sets this stream's exception handler to exceptionListener .
void setPersistenceDelegate(class<?> type, PersistenceDelegate delegate) -- Associates the specified persistence delegate with the given type.
void writeExpression(Expression oldExp) -- This implementation first checks whether an expression with that value has been written
protected void writeObject(Object o) -- Write the specified object to the output stream.
void writeStatement(Statement oldStm) -- Write statement oldStm to the stream.

public class XMLEncoder extends Encoder implements AutoCloseable

void close()
void flush()
Object getOwner() -- Gets the owner of this encoder.
void setOwner(Object owner) -- Sets the owner of this encoder to owner .
void writeExpression(Expression oldExp) – Log the expression so that when the stream is flushed, the encoder will produce actual output.
void writeObject(Object o) -- Writes the XML representation of the specified object to the output.
void writeStatement(Statement oldStm) – Record the statement so that the encoder will produce actual output when the stream is flushed.

public class XMLDecoder implements AutoCloseable

void close()
static DefaultHandler createHandler(Object owner, ExceptionListener el, ClassLoader cl)
-- Create a new handler for the SAX parser that can be used to parse embedded XML archives created by the XMLEncoder class.
ExceptionListener getExceptionListener() -- Gets the exception handler for this stream.
Object getOwner() --Gets the owner of this decoder.
Object readObject() -- Read the next object from the underlying input stream.
void setExceptionListener(ExceptionListener exceptionListener) --Sets this stream's exception handler to exceptionListener .
void setOwner(Object owner) --Set the owner of this decoder to owner .

Persistent proxy class To achieve persistence, two classes, Encoder and XMLEncoder, are needed to implement persistence in the form of XML.
XMLDecoder exists alone and has a readObject method to read persistence information from XML files and reuse it in actual projects.

Simple example:

public class XMLEncoderTest {
    /**
     * Persistence strategy -- xml form
     * @param args
     */
    public static void main(String[] args) throws Exception {
        XMLEncoder e = new XMLEncoder(
        new BufferedOutputStream(
        new FileOutputStream("E:\JavaTest\XMLTest.xml")));
        e.writeObject(new JButton("Click me!"));
        e.close();
    }
}

Results of the:

It can be seen that XMLDecoder implements the xml data format after persistence.
XMLDecoder implements reverse operation (read xml file data into the stream):

public class XMLDecoderTest {
    /**
     * Persistence reverse operation -- xml format
     */
    public static void main(String[] args) throws FileNotFoundException {
        XMLDecoder d = new XMLDecoder(
                new BufferedInputStream(
                        new FileInputStream("E:\JavaTest\XMLTest.xml")
                )
        );
        Object result = d.readObject();
        d.close();
        System.out.println(result);
    }
}

Results of the:

It can be seen that there are so many xml formats, and what you end up with is just a JButton object.
Only one object is used here, and it is a JButton object, not a self-defined object.

Speaking of persistence operations, we have to mention Serializable, serialization and deserialization.
First create an entity class Student:

public class Student implements Serializable {
    private String name;
    private Integer age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public Integer getAge() {
        return age;
    }
}

Note that the Student class is not given a unique number here:

private static final long serialVersionUID = 1L;

Serialization operation (into file, normally into database):

public class SerInTest {
    public static void main(String[] args) throws IOException {
        Student s = new Student();
        s.setName("JarkChen");
        s.setAge(23);

        File f = new File("E:\JavaTest\SerTest.txt");
        if(!f.getParentFile().exists()) f.getParentFile().mkdirs();
        if(f.exists()) f.delete();
        ObjectOutputStream o = new ObjectOutputStream(
                new FileOutputStream(f)
        );
        o.writeObject(s);
        o.close();
    }
}

Results of the:

Deserialization:

public class SerOutTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        File f = new File("E:\JavaTest\SerTest.txt");
        if(f.exists()){
            ObjectInputStream o = new ObjectInputStream(
                    new FileInputStream(f)
            );
            Object result = o.readObject();
            o.close();
            System.out.println(result);
        } else {
          System.out.println("The File is not exists!");
        }
    }
}

Results of the;