序列化

2020-06-12  本文已影响0人  南园故剑00

1. 序列化的意义

  1. 含义

序列化就是把实体对象状态按照一定的格式写入到有序字节流,反序列化就是从有序字节流重建对象,恢复对象状态

  1. 意义

(1)永久性保存对象,保存对象的字节序列到本地文件或者数据库中;

(2)通过序列化以字节流的形式使对象在网络中进行传递和接收;

(3)通过序列化在进程间传递对象;

  1. 序列化算法一般会按步骤做如下事情

(1)将对象实例相关的类元数据输出。

(2)递归地输出类的超类描述直到不再有超类。

(3)类元数据完了以后,开始从最顶层的超类开始输出对象实例的实际数据值。

(4)从上至下递归输出实例的数据

2. 优劣指标:

  1. 序列化后的数据大小

  2. 序列化操作本省的速度以及系统资源开销:CPU、内存

3. JDK的序列化:

3.1 一个类只要实现了 java.io.Serializable 接口,那就可以被序列化

/**
 * @description:
 * @date : 2020/1/7 22:56
 * @author: zwz
 */
public interface ISerializer {

    <T> byte[] serializer(T obj);

    <T> T deSerializer(byte[] data, Class<T> clazz);
}

3.2 通过输出流 java.io.ObjectOutputStream 和对象输入流 java.io.ObjectInputStream 来实现

package com.gp.lock.serizlizer;

import java.io.*;

/**
 * @description: 基于JDK实现序列化
 * @date : 2020/1/7 22:58
 * @author: zwz
 */
public class JavaSerializer implements ISerializer {

    /**
     * 序列化
     * 使用输出流
     * @param obj
     * @param <T>
     * @return
     */
    public <T> byte[] serializer(T obj) {
        ByteArrayOutputStream byteArrayOutputStream = null;
        ObjectOutputStream objectOutputStream = null;
        try {
            byteArrayOutputStream = new ByteArrayOutputStream();
            objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(obj);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (objectOutputStream != null) {
                    objectOutputStream.close();
                }
                if (byteArrayOutputStream != null) {
                    byteArrayOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return byteArrayOutputStream.toByteArray();
    }

    /**
     * 反序列化
     * 使用输入流
     * @param data
     * @param clazz
     * @param <T>
     * @return
     */
    public <T> T deSerializer(byte[] data, Class<T> clazz) {
        ByteArrayInputStream byteArrayInputStream = null;
        ObjectInputStream objectInputStream = null;
        Object result = null;

        try {
            byteArrayInputStream = new ByteArrayInputStream(data);
            objectInputStream = new ObjectInputStream(byteArrayInputStream);
            result = objectInputStream.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                if (byteArrayInputStream != null) {
                    byteArrayInputStream.close();
                }
                if (objectInputStream != null) {
                    objectInputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return (T) result;
    }
}

3.3 实例

package com.gp.lock.serizlizer;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Arrays;

/**
 * @description:
 * @date : 2020/1/7 23:11
 * @author: zwz
 */
public class User /*extends SuperClass*/ implements Serializable {

    private static final long serialVersionUID = 6322539910270175988L;

    public static int num = 5;

    private String name;

    private int age;

    private transient String hobby;

    public String getHobby() {
        return hobby;
    }

    public void setHobby(String hobby) {
        this.hobby = hobby;
    }

    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;
    }

    public static int getNum() {
        return num;
    }

    public static void setNum(int num) {
        User.num = num;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", hobby='" + hobby + '\'' +
                '}';
    }

    private void writeObject(ObjectOutputStream outputStream) throws IOException {
        outputStream.defaultWriteObject();
        outputStream.writeObject(hobby);
    }

    private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
        inputStream.defaultReadObject();
        hobby = (String) inputStream.readObject();
    }

    public static void main(String[] args) {
        ISerializer serializer = new JavaSerializer();
        User user = new User();
        user.setAge(18);
        user.setName("mic");

        byte[] bytes = serializer.serializer(user);
        System.out.println(Arrays.toString(bytes));

        User deSerializer = serializer.deSerializer(bytes, User.class);
        System.out.println(deSerializer);
    }
}

4. 高阶认识

4.1 serialVersionUID 的作用

4.2 静态变量序列化

序列化保存的是对象的状态,静态变量属于类的状态,因此序列化并不保存静态变量。

4.3 父类的序列化

  1. 当一个父类没有实现序列化时,子类继承该父类并且实现了序列化。在反序列化该子类后,是没办法获取到父类的属性的。

  2. 当一个父类实现序列化,子类自动实现序列化,不需要再显示实现Serializable 接口

  3. 当一个对象的实例变量引用了其他对象,序列化该对象时也会把引用对象进行序列化,但是前提是该引用对象必须实现序列化接口

4.4 Transient

5. 序列化实现深拷贝

  1. 浅克隆:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象

  2. 深克隆:

package com.zwz.serializer;

import java.io.*;

/**
 * @description: 实现深克隆效果
 * 把对象序列化输出到一个流中,然后对象序列化流中读取出来,这个对象就不是原来的对象了。
 * @date : 2020/1/8 15:23
 * @author: zwz
 */
public class Person implements Cloneable, Serializable {

    private static final long serialVersionUID = 5532843697249498959L;

    private String name;

    private Email email;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Email getEmail() {
        return email;
    }

    public void setEmail(Email email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", email=" + email.getContent() +
                '}';
    }

    @Override
    protected Person clone() throws CloneNotSupportedException {
        return (Person) super.clone();
    }

    public Person deepClone() throws IOException, ClassNotFoundException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(this);

        byte[] data = byteArrayOutputStream.toByteArray();

        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data);
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        Object object = objectInputStream.readObject();
        return (Person) object;
    }

    public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
        Email email = new Email();
        email.setContent("8:00");

        Person person = new Person();
        person.setName("mic");
        person.setEmail(email);

        Person person1 = person.deepClone();
        person1.setName("mak");
        person1.getEmail().setContent("9:00");

        System.out.println(person.getName() + "->" + person.getEmail().getContent());
        System.out.println(person1.getName() + "->" + person1.getEmail().getContent());

        System.out.println("-------------");

        Person person2 = person.clone();
        person2.setName("mac");
        person2.getEmail().setContent("10:00");

        System.out.println(person.getName() + "->" + person.getEmail().getContent());
        System.out.println(person1.getName() + "->" + person1.getEmail().getContent());
        System.out.println(person2.getName() + "->" + person2.getEmail().getContent());
    }

    /**
     * @description:
     * @date : 2020/1/8 15:21
     * @author: zwz
     */
    public static class Email implements Serializable {

        private static final long serialVersionUID = -2800552551799395733L;

        public Email(String content) {
            this.content = content;
        }

        private String content;

        public Email() {

        }

        public String getContent() {
            return content;
        }

        public void setContent(String content) {
            this.content = content;
        }
    }
}

6. 常见的序列化技术

6.1 使用 JAVA 进行序列化有他的优点,也有他的缺点

6.2 XML 序列化框架

package com.gp.lock.serizlizer;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

/**
 * @description:
 * @date : 2020/1/8 15:54
 * @author: zwz
 */
public class XmlSerializer implements ISerializer {

    XStream xStream = new XStream(new DomDriver());

    public <T> byte[] serializer(T obj) {
        return xStream.toXML(obj).getBytes();
    }

    public <T> T deSerializer(byte[] data, Class<T> clazz) {
        return (T) xStream.fromXML(new String(data));
    }
}

6.3 JSON 序列化

package com.gp.lock.serizlizer;

import com.alibaba.fastjson.JSON;

/**
 * @description:
 * @date : 2020/1/8 16:12
 * @author: zwz
 */
public class FastJsonSerializer implements ISerializer {

    public <T> byte[] serializer(T obj) {
        return JSON.toJSONString(obj).getBytes();
    }

    public <T> T deSerializer(byte[] data, Class<T> clazz) {
        return JSON.parseObject(new String(data), clazz);
    }
}

6.4 Hessian 序列化框架

7. Protobuf(Protocol Buffer) 序列化框架

7.1 简介

7.2 使用实例

  1. 到官网下载protobuf的相应版本,我这里下载的是windows下的3.1.0版protoc-3.1.0-win32.zip

  2. 将下载好的zip解压,能看到bin目录下有一个protoc.exe的文件,等下需要用它来编译文件,我们直接在bin目录下创建一个简单的person.proto的描述文件

syntax = "proto3";

option java_package = "com.gp.lock.serizlizer.protobuf";
option java_outer_classname = "PersonFactory";

message Person{

     int32 id = 1;
     string name = 2;
     int32 age = 3;
     Addr addr = 4;
   
}

message Addr{
     
     string contry = 1;
     string city = 2;

}
  1. 使用protoc编译上述.proto文件,生成Java类,使用如下命令完成该操作:protoc --java_out=./ ./person.proto

  2. 将PersonFactory.java文件引入到我们的项目中,并引入对应版本的protobuf的依赖包

// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: person.proto

package com.gp.lock.serizlizer.protobuf;

public final class PersonFactory {
    private PersonFactory() {
    }

    public static void registerAllExtensions(
            com.google.protobuf.ExtensionRegistryLite registry) {
    }

    public static void registerAllExtensions(
            com.google.protobuf.ExtensionRegistry registry) {
        registerAllExtensions(
                (com.google.protobuf.ExtensionRegistryLite) registry);
    }

    public interface PersonOrBuilder extends
            // @@protoc_insertion_point(interface_extends:Person)
            com.google.protobuf.MessageOrBuilder {

        /**
         * <code>optional int32 id = 1;</code>
         */
        int getId();

        /**
         * <code>optional string name = 2;</code>
         */
        String getName();

        /**
         * <code>optional string name = 2;</code>
         */
        com.google.protobuf.ByteString
        getNameBytes();

        /**
         * <code>optional int32 age = 3;</code>
         */
        int getAge();

        /**
         * <code>optional .Addr addr = 4;</code>
         */
        boolean hasAddr();

        /**
         * <code>optional .Addr addr = 4;</code>
         */
        Addr getAddr();

        /**
         * <code>optional .Addr addr = 4;</code>
         */
        AddrOrBuilder getAddrOrBuilder();
    }

    /**
     * Protobuf type {@code Person}
     */
    public static final class Person extends
            com.google.protobuf.GeneratedMessageV3 implements
            // @@protoc_insertion_point(message_implements:Person)
            PersonOrBuilder {
        // Use Person.newBuilder() to construct.
        private Person(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
            super(builder);
        }

        private Person() {
            id_ = 0;
            name_ = "";
            age_ = 0;
        }

        @Override
        public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
            return com.google.protobuf.UnknownFieldSet.getDefaultInstance();
        }

        private Person(
                com.google.protobuf.CodedInputStream input,
                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                throws com.google.protobuf.InvalidProtocolBufferException {
            this();
            int mutable_bitField0_ = 0;
            try {
                boolean done = false;
                while (!done) {
                    int tag = input.readTag();
                    switch (tag) {
                        case 0:
                            done = true;
                            break;
                        default: {
                            if (!input.skipField(tag)) {
                                done = true;
                            }
                            break;
                        }
                        case 8: {

                            id_ = input.readInt32();
                            break;
                        }
                        case 18: {
                            String s = input.readStringRequireUtf8();

                            name_ = s;
                            break;
                        }
                        case 24: {

                            age_ = input.readInt32();
                            break;
                        }
                        case 34: {
                            Addr.Builder subBuilder = null;
                            if (addr_ != null) {
                                subBuilder = addr_.toBuilder();
                            }
                            addr_ = input.readMessage(Addr.parser(), extensionRegistry);
                            if (subBuilder != null) {
                                subBuilder.mergeFrom(addr_);
                                addr_ = subBuilder.buildPartial();
                            }

                            break;
                        }
                    }
                }
            } catch (com.google.protobuf.InvalidProtocolBufferException e) {
                throw e.setUnfinishedMessage(this);
            } catch (java.io.IOException e) {
                throw new com.google.protobuf.InvalidProtocolBufferException(
                        e).setUnfinishedMessage(this);
            } finally {
                makeExtensionsImmutable();
            }
        }

        public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
            return PersonFactory.internal_static_Person_descriptor;
        }

        protected FieldAccessorTable
        internalGetFieldAccessorTable() {
            return PersonFactory.internal_static_Person_fieldAccessorTable
                    .ensureFieldAccessorsInitialized(
                            Person.class, Builder.class);
        }

        public static final int ID_FIELD_NUMBER = 1;
        private int id_;

        /**
         * <code>optional int32 id = 1;</code>
         */
        public int getId() {
            return id_;
        }

        public static final int NAME_FIELD_NUMBER = 2;
        private volatile Object name_;

        /**
         * <code>optional string name = 2;</code>
         */
        public String getName() {
            Object ref = name_;
            if (ref instanceof String) {
                return (String) ref;
            } else {
                com.google.protobuf.ByteString bs =
                        (com.google.protobuf.ByteString) ref;
                String s = bs.toStringUtf8();
                name_ = s;
                return s;
            }
        }

        /**
         * <code>optional string name = 2;</code>
         */
        public com.google.protobuf.ByteString
        getNameBytes() {
            Object ref = name_;
            if (ref instanceof String) {
                com.google.protobuf.ByteString b =
                        com.google.protobuf.ByteString.copyFromUtf8(
                                (String) ref);
                name_ = b;
                return b;
            } else {
                return (com.google.protobuf.ByteString) ref;
            }
        }

        public static final int AGE_FIELD_NUMBER = 3;
        private int age_;

        /**
         * <code>optional int32 age = 3;</code>
         */
        public int getAge() {
            return age_;
        }

        public static final int ADDR_FIELD_NUMBER = 4;
        private Addr addr_;

        /**
         * <code>optional .Addr addr = 4;</code>
         */
        public boolean hasAddr() {
            return addr_ != null;
        }

        /**
         * <code>optional .Addr addr = 4;</code>
         */
        public Addr getAddr() {
            return addr_ == null ? Addr.getDefaultInstance() : addr_;
        }

        /**
         * <code>optional .Addr addr = 4;</code>
         */
        public AddrOrBuilder getAddrOrBuilder() {
            return getAddr();
        }

        private byte memoizedIsInitialized = -1;

        public final boolean isInitialized() {
            byte isInitialized = memoizedIsInitialized;
            if (isInitialized == 1) return true;
            if (isInitialized == 0) return false;

            memoizedIsInitialized = 1;
            return true;
        }

        public void writeTo(com.google.protobuf.CodedOutputStream output)
                throws java.io.IOException {
            if (id_ != 0) {
                output.writeInt32(1, id_);
            }
            if (!getNameBytes().isEmpty()) {
                com.google.protobuf.GeneratedMessageV3.writeString(output, 2, name_);
            }
            if (age_ != 0) {
                output.writeInt32(3, age_);
            }
            if (addr_ != null) {
                output.writeMessage(4, getAddr());
            }
        }

        public int getSerializedSize() {
            int size = memoizedSize;
            if (size != -1) return size;

            size = 0;
            if (id_ != 0) {
                size += com.google.protobuf.CodedOutputStream
                        .computeInt32Size(1, id_);
            }
            if (!getNameBytes().isEmpty()) {
                size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, name_);
            }
            if (age_ != 0) {
                size += com.google.protobuf.CodedOutputStream
                        .computeInt32Size(3, age_);
            }
            if (addr_ != null) {
                size += com.google.protobuf.CodedOutputStream
                        .computeMessageSize(4, getAddr());
            }
            memoizedSize = size;
            return size;
        }

        private static final long serialVersionUID = 0L;

        @Override
        public boolean equals(final Object obj) {
            if (obj == this) {
                return true;
            }
            if (!(obj instanceof Person)) {
                return super.equals(obj);
            }
            Person other = (Person) obj;

            boolean result = true;
            result = result && (getId()
                    == other.getId());
            result = result && getName()
                    .equals(other.getName());
            result = result && (getAge()
                    == other.getAge());
            result = result && (hasAddr() == other.hasAddr());
            if (hasAddr()) {
                result = result && getAddr()
                        .equals(other.getAddr());
            }
            return result;
        }

        @Override
        public int hashCode() {
            if (memoizedHashCode != 0) {
                return memoizedHashCode;
            }
            int hash = 41;
            hash = (19 * hash) + getDescriptorForType().hashCode();
            hash = (37 * hash) + ID_FIELD_NUMBER;
            hash = (53 * hash) + getId();
            hash = (37 * hash) + NAME_FIELD_NUMBER;
            hash = (53 * hash) + getName().hashCode();
            hash = (37 * hash) + AGE_FIELD_NUMBER;
            hash = (53 * hash) + getAge();
            if (hasAddr()) {
                hash = (37 * hash) + ADDR_FIELD_NUMBER;
                hash = (53 * hash) + getAddr().hashCode();
            }
            hash = (29 * hash) + unknownFields.hashCode();
            memoizedHashCode = hash;
            return hash;
        }

        public static Person parseFrom(
                com.google.protobuf.ByteString data)
                throws com.google.protobuf.InvalidProtocolBufferException {
            return PARSER.parseFrom(data);
        }

        public static Person parseFrom(
                com.google.protobuf.ByteString data,
                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                throws com.google.protobuf.InvalidProtocolBufferException {
            return PARSER.parseFrom(data, extensionRegistry);
        }

        public static Person parseFrom(byte[] data)
                throws com.google.protobuf.InvalidProtocolBufferException {
            return PARSER.parseFrom(data);
        }

        public static Person parseFrom(
                byte[] data,
                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                throws com.google.protobuf.InvalidProtocolBufferException {
            return PARSER.parseFrom(data, extensionRegistry);
        }

        public static Person parseFrom(java.io.InputStream input)
                throws java.io.IOException {
            return com.google.protobuf.GeneratedMessageV3
                    .parseWithIOException(PARSER, input);
        }

        public static Person parseFrom(
                java.io.InputStream input,
                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                throws java.io.IOException {
            return com.google.protobuf.GeneratedMessageV3
                    .parseWithIOException(PARSER, input, extensionRegistry);
        }

        public static Person parseDelimitedFrom(java.io.InputStream input)
                throws java.io.IOException {
            return com.google.protobuf.GeneratedMessageV3
                    .parseDelimitedWithIOException(PARSER, input);
        }

        public static Person parseDelimitedFrom(
                java.io.InputStream input,
                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                throws java.io.IOException {
            return com.google.protobuf.GeneratedMessageV3
                    .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
        }

        public static Person parseFrom(
                com.google.protobuf.CodedInputStream input)
                throws java.io.IOException {
            return com.google.protobuf.GeneratedMessageV3
                    .parseWithIOException(PARSER, input);
        }

        public static Person parseFrom(
                com.google.protobuf.CodedInputStream input,
                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                throws java.io.IOException {
            return com.google.protobuf.GeneratedMessageV3
                    .parseWithIOException(PARSER, input, extensionRegistry);
        }

        public Builder newBuilderForType() {
            return newBuilder();
        }

        public static Builder newBuilder() {
            return DEFAULT_INSTANCE.toBuilder();
        }

        public static Builder newBuilder(Person prototype) {
            return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
        }

        public Builder toBuilder() {
            return this == DEFAULT_INSTANCE
                    ? new Builder() : new Builder().mergeFrom(this);
        }

        @Override
        protected Builder newBuilderForType(
                BuilderParent parent) {
            Builder builder = new Builder(parent);
            return builder;
        }

        /**
         * Protobuf type {@code Person}
         */
        public static final class Builder extends
                com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
                // @@protoc_insertion_point(builder_implements:Person)
                PersonOrBuilder {
            public static final com.google.protobuf.Descriptors.Descriptor
            getDescriptor() {
                return PersonFactory.internal_static_Person_descriptor;
            }

            protected FieldAccessorTable
            internalGetFieldAccessorTable() {
                return PersonFactory.internal_static_Person_fieldAccessorTable
                        .ensureFieldAccessorsInitialized(
                                Person.class, Builder.class);
            }

            // Construct using com.gp.lock.serizlizer.protobuf.PersonFactory.Person.newBuilder()
            private Builder() {
                maybeForceBuilderInitialization();
            }

            private Builder(
                    BuilderParent parent) {
                super(parent);
                maybeForceBuilderInitialization();
            }

            private void maybeForceBuilderInitialization() {
                if (com.google.protobuf.GeneratedMessageV3
                        .alwaysUseFieldBuilders) {
                }
            }

            public Builder clear() {
                super.clear();
                id_ = 0;

                name_ = "";

                age_ = 0;

                if (addrBuilder_ == null) {
                    addr_ = null;
                } else {
                    addr_ = null;
                    addrBuilder_ = null;
                }
                return this;
            }

            public com.google.protobuf.Descriptors.Descriptor
            getDescriptorForType() {
                return PersonFactory.internal_static_Person_descriptor;
            }

            public Person getDefaultInstanceForType() {
                return Person.getDefaultInstance();
            }

            public Person build() {
                Person result = buildPartial();
                if (!result.isInitialized()) {
                    throw newUninitializedMessageException(result);
                }
                return result;
            }

            public Person buildPartial() {
                Person result = new Person(this);
                result.id_ = id_;
                result.name_ = name_;
                result.age_ = age_;
                if (addrBuilder_ == null) {
                    result.addr_ = addr_;
                } else {
                    result.addr_ = addrBuilder_.build();
                }
                onBuilt();
                return result;
            }

            public Builder clone() {
                return (Builder) super.clone();
            }

            public Builder setField(
                    com.google.protobuf.Descriptors.FieldDescriptor field,
                    Object value) {
                return (Builder) super.setField(field, value);
            }

            public Builder clearField(
                    com.google.protobuf.Descriptors.FieldDescriptor field) {
                return (Builder) super.clearField(field);
            }

            public Builder clearOneof(
                    com.google.protobuf.Descriptors.OneofDescriptor oneof) {
                return (Builder) super.clearOneof(oneof);
            }

            public Builder setRepeatedField(
                    com.google.protobuf.Descriptors.FieldDescriptor field,
                    int index, Object value) {
                return (Builder) super.setRepeatedField(field, index, value);
            }

            public Builder addRepeatedField(
                    com.google.protobuf.Descriptors.FieldDescriptor field,
                    Object value) {
                return (Builder) super.addRepeatedField(field, value);
            }

            public Builder mergeFrom(com.google.protobuf.Message other) {
                if (other instanceof Person) {
                    return mergeFrom((Person) other);
                } else {
                    super.mergeFrom(other);
                    return this;
                }
            }

            public Builder mergeFrom(Person other) {
                if (other == Person.getDefaultInstance()) return this;
                if (other.getId() != 0) {
                    setId(other.getId());
                }
                if (!other.getName().isEmpty()) {
                    name_ = other.name_;
                    onChanged();
                }
                if (other.getAge() != 0) {
                    setAge(other.getAge());
                }
                if (other.hasAddr()) {
                    mergeAddr(other.getAddr());
                }
                onChanged();
                return this;
            }

            public final boolean isInitialized() {
                return true;
            }

            public Builder mergeFrom(
                    com.google.protobuf.CodedInputStream input,
                    com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                    throws java.io.IOException {
                Person parsedMessage = null;
                try {
                    parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
                } catch (com.google.protobuf.InvalidProtocolBufferException e) {
                    parsedMessage = (Person) e.getUnfinishedMessage();
                    throw e.unwrapIOException();
                } finally {
                    if (parsedMessage != null) {
                        mergeFrom(parsedMessage);
                    }
                }
                return this;
            }

            private int id_;

            /**
             * <code>optional int32 id = 1;</code>
             */
            public int getId() {
                return id_;
            }

            /**
             * <code>optional int32 id = 1;</code>
             */
            public Builder setId(int value) {

                id_ = value;
                onChanged();
                return this;
            }

            /**
             * <code>optional int32 id = 1;</code>
             */
            public Builder clearId() {

                id_ = 0;
                onChanged();
                return this;
            }

            private Object name_ = "";

            /**
             * <code>optional string name = 2;</code>
             */
            public String getName() {
                Object ref = name_;
                if (!(ref instanceof String)) {
                    com.google.protobuf.ByteString bs =
                            (com.google.protobuf.ByteString) ref;
                    String s = bs.toStringUtf8();
                    name_ = s;
                    return s;
                } else {
                    return (String) ref;
                }
            }

            /**
             * <code>optional string name = 2;</code>
             */
            public com.google.protobuf.ByteString
            getNameBytes() {
                Object ref = name_;
                if (ref instanceof String) {
                    com.google.protobuf.ByteString b =
                            com.google.protobuf.ByteString.copyFromUtf8(
                                    (String) ref);
                    name_ = b;
                    return b;
                } else {
                    return (com.google.protobuf.ByteString) ref;
                }
            }

            /**
             * <code>optional string name = 2;</code>
             */
            public Builder setName(
                    String value) {
                if (value == null) {
                    throw new NullPointerException();
                }

                name_ = value;
                onChanged();
                return this;
            }

            /**
             * <code>optional string name = 2;</code>
             */
            public Builder clearName() {

                name_ = getDefaultInstance().getName();
                onChanged();
                return this;
            }

            /**
             * <code>optional string name = 2;</code>
             */
            public Builder setNameBytes(
                    com.google.protobuf.ByteString value) {
                if (value == null) {
                    throw new NullPointerException();
                }
                checkByteStringIsUtf8(value);

                name_ = value;
                onChanged();
                return this;
            }

            private int age_;

            /**
             * <code>optional int32 age = 3;</code>
             */
            public int getAge() {
                return age_;
            }

            /**
             * <code>optional int32 age = 3;</code>
             */
            public Builder setAge(int value) {

                age_ = value;
                onChanged();
                return this;
            }

            /**
             * <code>optional int32 age = 3;</code>
             */
            public Builder clearAge() {

                age_ = 0;
                onChanged();
                return this;
            }

            private Addr addr_ = null;
            private com.google.protobuf.SingleFieldBuilderV3<
                    Addr, Addr.Builder, AddrOrBuilder> addrBuilder_;

            /**
             * <code>optional .Addr addr = 4;</code>
             */
            public boolean hasAddr() {
                return addrBuilder_ != null || addr_ != null;
            }

            /**
             * <code>optional .Addr addr = 4;</code>
             */
            public Addr getAddr() {
                if (addrBuilder_ == null) {
                    return addr_ == null ? Addr.getDefaultInstance() : addr_;
                } else {
                    return addrBuilder_.getMessage();
                }
            }

            /**
             * <code>optional .Addr addr = 4;</code>
             */
            public Builder setAddr(Addr value) {
                if (addrBuilder_ == null) {
                    if (value == null) {
                        throw new NullPointerException();
                    }
                    addr_ = value;
                    onChanged();
                } else {
                    addrBuilder_.setMessage(value);
                }

                return this;
            }

            /**
             * <code>optional .Addr addr = 4;</code>
             */
            public Builder setAddr(
                    Addr.Builder builderForValue) {
                if (addrBuilder_ == null) {
                    addr_ = builderForValue.build();
                    onChanged();
                } else {
                    addrBuilder_.setMessage(builderForValue.build());
                }

                return this;
            }

            /**
             * <code>optional .Addr addr = 4;</code>
             */
            public Builder mergeAddr(Addr value) {
                if (addrBuilder_ == null) {
                    if (addr_ != null) {
                        addr_ =
                                Addr.newBuilder(addr_).mergeFrom(value).buildPartial();
                    } else {
                        addr_ = value;
                    }
                    onChanged();
                } else {
                    addrBuilder_.mergeFrom(value);
                }

                return this;
            }

            /**
             * <code>optional .Addr addr = 4;</code>
             */
            public Builder clearAddr() {
                if (addrBuilder_ == null) {
                    addr_ = null;
                    onChanged();
                } else {
                    addr_ = null;
                    addrBuilder_ = null;
                }

                return this;
            }

            /**
             * <code>optional .Addr addr = 4;</code>
             */
            public Addr.Builder getAddrBuilder() {

                onChanged();
                return getAddrFieldBuilder().getBuilder();
            }

            /**
             * <code>optional .Addr addr = 4;</code>
             */
            public AddrOrBuilder getAddrOrBuilder() {
                if (addrBuilder_ != null) {
                    return addrBuilder_.getMessageOrBuilder();
                } else {
                    return addr_ == null ?
                            Addr.getDefaultInstance() : addr_;
                }
            }

            /**
             * <code>optional .Addr addr = 4;</code>
             */
            private com.google.protobuf.SingleFieldBuilderV3<
                    Addr, Addr.Builder, AddrOrBuilder>
            getAddrFieldBuilder() {
                if (addrBuilder_ == null) {
                    addrBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
                            Addr, Addr.Builder, AddrOrBuilder>(
                            getAddr(),
                            getParentForChildren(),
                            isClean());
                    addr_ = null;
                }
                return addrBuilder_;
            }

            public final Builder setUnknownFields(
                    final com.google.protobuf.UnknownFieldSet unknownFields) {
                return this;
            }

            public final Builder mergeUnknownFields(
                    final com.google.protobuf.UnknownFieldSet unknownFields) {
                return this;
            }


            // @@protoc_insertion_point(builder_scope:Person)
        }

        // @@protoc_insertion_point(class_scope:Person)
        private static final Person DEFAULT_INSTANCE;

        static {
            DEFAULT_INSTANCE = new Person();
        }

        public static Person getDefaultInstance() {
            return DEFAULT_INSTANCE;
        }

        private static final com.google.protobuf.Parser<Person>
                PARSER = new com.google.protobuf.AbstractParser<Person>() {
            public Person parsePartialFrom(
                    com.google.protobuf.CodedInputStream input,
                    com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                    throws com.google.protobuf.InvalidProtocolBufferException {
                return new Person(input, extensionRegistry);
            }
        };

        public static com.google.protobuf.Parser<Person> parser() {
            return PARSER;
        }

        @Override
        public com.google.protobuf.Parser<Person> getParserForType() {
            return PARSER;
        }

        public Person getDefaultInstanceForType() {
            return DEFAULT_INSTANCE;
        }

    }

    public interface AddrOrBuilder extends
            // @@protoc_insertion_point(interface_extends:Addr)
            com.google.protobuf.MessageOrBuilder {

        /**
         * <code>optional string contry = 1;</code>
         */
        String getContry();

        /**
         * <code>optional string contry = 1;</code>
         */
        com.google.protobuf.ByteString
        getContryBytes();

        /**
         * <code>optional string city = 2;</code>
         */
        String getCity();

        /**
         * <code>optional string city = 2;</code>
         */
        com.google.protobuf.ByteString
        getCityBytes();
    }

    /**
     * Protobuf type {@code Addr}
     */
    public static final class Addr extends
            com.google.protobuf.GeneratedMessageV3 implements
            // @@protoc_insertion_point(message_implements:Addr)
            AddrOrBuilder {
        // Use Addr.newBuilder() to construct.
        private Addr(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
            super(builder);
        }

        private Addr() {
            contry_ = "";
            city_ = "";
        }

        @Override
        public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
            return com.google.protobuf.UnknownFieldSet.getDefaultInstance();
        }

        private Addr(
                com.google.protobuf.CodedInputStream input,
                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                throws com.google.protobuf.InvalidProtocolBufferException {
            this();
            int mutable_bitField0_ = 0;
            try {
                boolean done = false;
                while (!done) {
                    int tag = input.readTag();
                    switch (tag) {
                        case 0:
                            done = true;
                            break;
                        default: {
                            if (!input.skipField(tag)) {
                                done = true;
                            }
                            break;
                        }
                        case 10: {
                            String s = input.readStringRequireUtf8();

                            contry_ = s;
                            break;
                        }
                        case 18: {
                            String s = input.readStringRequireUtf8();

                            city_ = s;
                            break;
                        }
                    }
                }
            } catch (com.google.protobuf.InvalidProtocolBufferException e) {
                throw e.setUnfinishedMessage(this);
            } catch (java.io.IOException e) {
                throw new com.google.protobuf.InvalidProtocolBufferException(
                        e).setUnfinishedMessage(this);
            } finally {
                makeExtensionsImmutable();
            }
        }

        public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
            return PersonFactory.internal_static_Addr_descriptor;
        }

        protected FieldAccessorTable
        internalGetFieldAccessorTable() {
            return PersonFactory.internal_static_Addr_fieldAccessorTable
                    .ensureFieldAccessorsInitialized(
                            Addr.class, Builder.class);
        }

        public static final int CONTRY_FIELD_NUMBER = 1;
        private volatile Object contry_;

        /**
         * <code>optional string contry = 1;</code>
         */
        public String getContry() {
            Object ref = contry_;
            if (ref instanceof String) {
                return (String) ref;
            } else {
                com.google.protobuf.ByteString bs =
                        (com.google.protobuf.ByteString) ref;
                String s = bs.toStringUtf8();
                contry_ = s;
                return s;
            }
        }

        /**
         * <code>optional string contry = 1;</code>
         */
        public com.google.protobuf.ByteString
        getContryBytes() {
            Object ref = contry_;
            if (ref instanceof String) {
                com.google.protobuf.ByteString b =
                        com.google.protobuf.ByteString.copyFromUtf8(
                                (String) ref);
                contry_ = b;
                return b;
            } else {
                return (com.google.protobuf.ByteString) ref;
            }
        }

        public static final int CITY_FIELD_NUMBER = 2;
        private volatile Object city_;

        /**
         * <code>optional string city = 2;</code>
         */
        public String getCity() {
            Object ref = city_;
            if (ref instanceof String) {
                return (String) ref;
            } else {
                com.google.protobuf.ByteString bs =
                        (com.google.protobuf.ByteString) ref;
                String s = bs.toStringUtf8();
                city_ = s;
                return s;
            }
        }

        /**
         * <code>optional string city = 2;</code>
         */
        public com.google.protobuf.ByteString
        getCityBytes() {
            Object ref = city_;
            if (ref instanceof String) {
                com.google.protobuf.ByteString b =
                        com.google.protobuf.ByteString.copyFromUtf8(
                                (String) ref);
                city_ = b;
                return b;
            } else {
                return (com.google.protobuf.ByteString) ref;
            }
        }

        private byte memoizedIsInitialized = -1;

        public final boolean isInitialized() {
            byte isInitialized = memoizedIsInitialized;
            if (isInitialized == 1) return true;
            if (isInitialized == 0) return false;

            memoizedIsInitialized = 1;
            return true;
        }

        public void writeTo(com.google.protobuf.CodedOutputStream output)
                throws java.io.IOException {
            if (!getContryBytes().isEmpty()) {
                com.google.protobuf.GeneratedMessageV3.writeString(output, 1, contry_);
            }
            if (!getCityBytes().isEmpty()) {
                com.google.protobuf.GeneratedMessageV3.writeString(output, 2, city_);
            }
        }

        public int getSerializedSize() {
            int size = memoizedSize;
            if (size != -1) return size;

            size = 0;
            if (!getContryBytes().isEmpty()) {
                size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, contry_);
            }
            if (!getCityBytes().isEmpty()) {
                size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, city_);
            }
            memoizedSize = size;
            return size;
        }

        private static final long serialVersionUID = 0L;

        @Override
        public boolean equals(final Object obj) {
            if (obj == this) {
                return true;
            }
            if (!(obj instanceof Addr)) {
                return super.equals(obj);
            }
            Addr other = (Addr) obj;

            boolean result = true;
            result = result && getContry()
                    .equals(other.getContry());
            result = result && getCity()
                    .equals(other.getCity());
            return result;
        }

        @Override
        public int hashCode() {
            if (memoizedHashCode != 0) {
                return memoizedHashCode;
            }
            int hash = 41;
            hash = (19 * hash) + getDescriptorForType().hashCode();
            hash = (37 * hash) + CONTRY_FIELD_NUMBER;
            hash = (53 * hash) + getContry().hashCode();
            hash = (37 * hash) + CITY_FIELD_NUMBER;
            hash = (53 * hash) + getCity().hashCode();
            hash = (29 * hash) + unknownFields.hashCode();
            memoizedHashCode = hash;
            return hash;
        }

        public static Addr parseFrom(
                com.google.protobuf.ByteString data)
                throws com.google.protobuf.InvalidProtocolBufferException {
            return PARSER.parseFrom(data);
        }

        public static Addr parseFrom(
                com.google.protobuf.ByteString data,
                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                throws com.google.protobuf.InvalidProtocolBufferException {
            return PARSER.parseFrom(data, extensionRegistry);
        }

        public static Addr parseFrom(byte[] data)
                throws com.google.protobuf.InvalidProtocolBufferException {
            return PARSER.parseFrom(data);
        }

        public static Addr parseFrom(
                byte[] data,
                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                throws com.google.protobuf.InvalidProtocolBufferException {
            return PARSER.parseFrom(data, extensionRegistry);
        }

        public static Addr parseFrom(java.io.InputStream input)
                throws java.io.IOException {
            return com.google.protobuf.GeneratedMessageV3
                    .parseWithIOException(PARSER, input);
        }

        public static Addr parseFrom(
                java.io.InputStream input,
                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                throws java.io.IOException {
            return com.google.protobuf.GeneratedMessageV3
                    .parseWithIOException(PARSER, input, extensionRegistry);
        }

        public static Addr parseDelimitedFrom(java.io.InputStream input)
                throws java.io.IOException {
            return com.google.protobuf.GeneratedMessageV3
                    .parseDelimitedWithIOException(PARSER, input);
        }

        public static Addr parseDelimitedFrom(
                java.io.InputStream input,
                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                throws java.io.IOException {
            return com.google.protobuf.GeneratedMessageV3
                    .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
        }

        public static Addr parseFrom(
                com.google.protobuf.CodedInputStream input)
                throws java.io.IOException {
            return com.google.protobuf.GeneratedMessageV3
                    .parseWithIOException(PARSER, input);
        }

        public static Addr parseFrom(
                com.google.protobuf.CodedInputStream input,
                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                throws java.io.IOException {
            return com.google.protobuf.GeneratedMessageV3
                    .parseWithIOException(PARSER, input, extensionRegistry);
        }

        public Builder newBuilderForType() {
            return newBuilder();
        }

        public static Builder newBuilder() {
            return DEFAULT_INSTANCE.toBuilder();
        }

        public static Builder newBuilder(Addr prototype) {
            return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
        }

        public Builder toBuilder() {
            return this == DEFAULT_INSTANCE
                    ? new Builder() : new Builder().mergeFrom(this);
        }

        @Override
        protected Builder newBuilderForType(
                BuilderParent parent) {
            Builder builder = new Builder(parent);
            return builder;
        }

        /**
         * Protobuf type {@code Addr}
         */
        public static final class Builder extends
                com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
                // @@protoc_insertion_point(builder_implements:Addr)
                AddrOrBuilder {
            public static final com.google.protobuf.Descriptors.Descriptor
            getDescriptor() {
                return PersonFactory.internal_static_Addr_descriptor;
            }

            protected FieldAccessorTable
            internalGetFieldAccessorTable() {
                return PersonFactory.internal_static_Addr_fieldAccessorTable
                        .ensureFieldAccessorsInitialized(
                                Addr.class, Builder.class);
            }

            // Construct using com.gp.lock.serizlizer.protobuf.PersonFactory.Addr.newBuilder()
            private Builder() {
                maybeForceBuilderInitialization();
            }

            private Builder(
                    BuilderParent parent) {
                super(parent);
                maybeForceBuilderInitialization();
            }

            private void maybeForceBuilderInitialization() {
                if (com.google.protobuf.GeneratedMessageV3
                        .alwaysUseFieldBuilders) {
                }
            }

            public Builder clear() {
                super.clear();
                contry_ = "";

                city_ = "";

                return this;
            }

            public com.google.protobuf.Descriptors.Descriptor
            getDescriptorForType() {
                return PersonFactory.internal_static_Addr_descriptor;
            }

            public Addr getDefaultInstanceForType() {
                return Addr.getDefaultInstance();
            }

            public Addr build() {
                Addr result = buildPartial();
                if (!result.isInitialized()) {
                    throw newUninitializedMessageException(result);
                }
                return result;
            }

            public Addr buildPartial() {
                Addr result = new Addr(this);
                result.contry_ = contry_;
                result.city_ = city_;
                onBuilt();
                return result;
            }

            public Builder clone() {
                return (Builder) super.clone();
            }

            public Builder setField(
                    com.google.protobuf.Descriptors.FieldDescriptor field,
                    Object value) {
                return (Builder) super.setField(field, value);
            }

            public Builder clearField(
                    com.google.protobuf.Descriptors.FieldDescriptor field) {
                return (Builder) super.clearField(field);
            }

            public Builder clearOneof(
                    com.google.protobuf.Descriptors.OneofDescriptor oneof) {
                return (Builder) super.clearOneof(oneof);
            }

            public Builder setRepeatedField(
                    com.google.protobuf.Descriptors.FieldDescriptor field,
                    int index, Object value) {
                return (Builder) super.setRepeatedField(field, index, value);
            }

            public Builder addRepeatedField(
                    com.google.protobuf.Descriptors.FieldDescriptor field,
                    Object value) {
                return (Builder) super.addRepeatedField(field, value);
            }

            public Builder mergeFrom(com.google.protobuf.Message other) {
                if (other instanceof Addr) {
                    return mergeFrom((Addr) other);
                } else {
                    super.mergeFrom(other);
                    return this;
                }
            }

            public Builder mergeFrom(Addr other) {
                if (other == Addr.getDefaultInstance()) return this;
                if (!other.getContry().isEmpty()) {
                    contry_ = other.contry_;
                    onChanged();
                }
                if (!other.getCity().isEmpty()) {
                    city_ = other.city_;
                    onChanged();
                }
                onChanged();
                return this;
            }

            public final boolean isInitialized() {
                return true;
            }

            public Builder mergeFrom(
                    com.google.protobuf.CodedInputStream input,
                    com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                    throws java.io.IOException {
                Addr parsedMessage = null;
                try {
                    parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
                } catch (com.google.protobuf.InvalidProtocolBufferException e) {
                    parsedMessage = (Addr) e.getUnfinishedMessage();
                    throw e.unwrapIOException();
                } finally {
                    if (parsedMessage != null) {
                        mergeFrom(parsedMessage);
                    }
                }
                return this;
            }

            private Object contry_ = "";

            /**
             * <code>optional string contry = 1;</code>
             */
            public String getContry() {
                Object ref = contry_;
                if (!(ref instanceof String)) {
                    com.google.protobuf.ByteString bs =
                            (com.google.protobuf.ByteString) ref;
                    String s = bs.toStringUtf8();
                    contry_ = s;
                    return s;
                } else {
                    return (String) ref;
                }
            }

            /**
             * <code>optional string contry = 1;</code>
             */
            public com.google.protobuf.ByteString
            getContryBytes() {
                Object ref = contry_;
                if (ref instanceof String) {
                    com.google.protobuf.ByteString b =
                            com.google.protobuf.ByteString.copyFromUtf8(
                                    (String) ref);
                    contry_ = b;
                    return b;
                } else {
                    return (com.google.protobuf.ByteString) ref;
                }
            }

            /**
             * <code>optional string contry = 1;</code>
             */
            public Builder setContry(
                    String value) {
                if (value == null) {
                    throw new NullPointerException();
                }

                contry_ = value;
                onChanged();
                return this;
            }

            /**
             * <code>optional string contry = 1;</code>
             */
            public Builder clearContry() {

                contry_ = getDefaultInstance().getContry();
                onChanged();
                return this;
            }

            /**
             * <code>optional string contry = 1;</code>
             */
            public Builder setContryBytes(
                    com.google.protobuf.ByteString value) {
                if (value == null) {
                    throw new NullPointerException();
                }
                checkByteStringIsUtf8(value);

                contry_ = value;
                onChanged();
                return this;
            }

            private Object city_ = "";

            /**
             * <code>optional string city = 2;</code>
             */
            public String getCity() {
                Object ref = city_;
                if (!(ref instanceof String)) {
                    com.google.protobuf.ByteString bs =
                            (com.google.protobuf.ByteString) ref;
                    String s = bs.toStringUtf8();
                    city_ = s;
                    return s;
                } else {
                    return (String) ref;
                }
            }

            /**
             * <code>optional string city = 2;</code>
             */
            public com.google.protobuf.ByteString
            getCityBytes() {
                Object ref = city_;
                if (ref instanceof String) {
                    com.google.protobuf.ByteString b =
                            com.google.protobuf.ByteString.copyFromUtf8(
                                    (String) ref);
                    city_ = b;
                    return b;
                } else {
                    return (com.google.protobuf.ByteString) ref;
                }
            }

            /**
             * <code>optional string city = 2;</code>
             */
            public Builder setCity(
                    String value) {
                if (value == null) {
                    throw new NullPointerException();
                }

                city_ = value;
                onChanged();
                return this;
            }

            /**
             * <code>optional string city = 2;</code>
             */
            public Builder clearCity() {

                city_ = getDefaultInstance().getCity();
                onChanged();
                return this;
            }

            /**
             * <code>optional string city = 2;</code>
             */
            public Builder setCityBytes(
                    com.google.protobuf.ByteString value) {
                if (value == null) {
                    throw new NullPointerException();
                }
                checkByteStringIsUtf8(value);

                city_ = value;
                onChanged();
                return this;
            }

            public final Builder setUnknownFields(
                    final com.google.protobuf.UnknownFieldSet unknownFields) {
                return this;
            }

            public final Builder mergeUnknownFields(
                    final com.google.protobuf.UnknownFieldSet unknownFields) {
                return this;
            }


            // @@protoc_insertion_point(builder_scope:Addr)
        }

        // @@protoc_insertion_point(class_scope:Addr)
        private static final Addr DEFAULT_INSTANCE;

        static {
            DEFAULT_INSTANCE = new Addr();
        }

        public static Addr getDefaultInstance() {
            return DEFAULT_INSTANCE;
        }

        private static final com.google.protobuf.Parser<Addr>
                PARSER = new com.google.protobuf.AbstractParser<Addr>() {
            public Addr parsePartialFrom(
                    com.google.protobuf.CodedInputStream input,
                    com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                    throws com.google.protobuf.InvalidProtocolBufferException {
                return new Addr(input, extensionRegistry);
            }
        };

        public static com.google.protobuf.Parser<Addr> parser() {
            return PARSER;
        }

        @Override
        public com.google.protobuf.Parser<Addr> getParserForType() {
            return PARSER;
        }

        public Addr getDefaultInstanceForType() {
            return DEFAULT_INSTANCE;
        }

    }

    private static final com.google.protobuf.Descriptors.Descriptor
            internal_static_Person_descriptor;
    private static final
    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
            internal_static_Person_fieldAccessorTable;
    private static final com.google.protobuf.Descriptors.Descriptor
            internal_static_Addr_descriptor;
    private static final
    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
            internal_static_Addr_fieldAccessorTable;

    public static com.google.protobuf.Descriptors.FileDescriptor
    getDescriptor() {
        return descriptor;
    }

    private static com.google.protobuf.Descriptors.FileDescriptor
            descriptor;

    static {
        String[] descriptorData = {
                "\n\014person.proto\"D\n\006Person\022\n\n\002id\030\001 \001(\005\022\014\n\004" +
                        "name\030\002 \001(\t\022\013\n\003age\030\003 \001(\005\022\023\n\004addr\030\004 \001(\0132\005." +
                        "Addr\"$\n\004Addr\022\016\n\006contry\030\001 \001(\t\022\014\n\004city\030\002 \001" +
                        "(\tB0\n\037com.gp.lock.serizlizer.protobufB\rP" +
                        "ersonFactoryb\006proto3"
        };
        com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
                new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
                    public com.google.protobuf.ExtensionRegistry assignDescriptors(
                            com.google.protobuf.Descriptors.FileDescriptor root) {
                        descriptor = root;
                        return null;
                    }
                };
        com.google.protobuf.Descriptors.FileDescriptor
                .internalBuildGeneratedFileFrom(descriptorData,
                        new com.google.protobuf.Descriptors.FileDescriptor[]{
                        }, assigner);
        internal_static_Person_descriptor =
                getDescriptor().getMessageTypes().get(0);
        internal_static_Person_fieldAccessorTable = new
                com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
                internal_static_Person_descriptor,
                new String[]{"Id", "Name", "Age", "Addr",});
        internal_static_Addr_descriptor =
                getDescriptor().getMessageTypes().get(1);
        internal_static_Addr_fieldAccessorTable = new
                com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
                internal_static_Addr_descriptor,
                new String[]{"Contry", "City",});
    }

    // @@protoc_insertion_point(outer_class_scope)
}

package com.gp.lock.serizlizer.protobuf;

import java.net.ServerSocket;
import java.net.Socket;

public class Server {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        ServerSocket serverSock = new ServerSocket(3030);
        while (true) {
            Socket sock = serverSock.accept();
            byte[] msg = new byte[256];
            sock.getInputStream().read(msg);
            int msgBodyLen = msg[0];
            System.out.println("msg body len:" + msgBodyLen);
            byte[] msgbody = new byte[msgBodyLen];
            System.arraycopy(msg, 1, msgbody, 0, msgBodyLen);

            System.out.println("msgbody = " + new String(msgbody));
            PersonFactory.Person person = PersonFactory.Person.parseFrom(msgbody);

            System.out.println("Receive:");
            System.out.println(person);
        }

    }

}

package com.gp.lock.serizlizer.protobuf;

import com.gp.lock.serizlizer.protobuf.PersonFactory.Addr;
import com.gp.lock.serizlizer.protobuf.PersonFactory.Person;

import java.net.Socket;

public class Client {

    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("127.0.0.1", 3030);

        Person.Builder person = Person.newBuilder();

        Addr.Builder addr = Addr.newBuilder();
        addr.setContry("china").setCity("shenzhen");

        person.setId(1).setAge(12).setName("ccf");
        person.setAddr(addr);

        byte[] messageBody = person.build().toByteArray();

        System.out.println("messageBody = " + new String(messageBody));
        int headerLen = 1;
        byte[] message = new byte[headerLen + messageBody.length];
        message[0] = (byte) messageBody.length;
        System.arraycopy(messageBody, 0, message, 1, messageBody.length);
        System.out.println("msg len:" + message.length);
        socket.getOutputStream().write(message);
    }

}

结果

"C:\Program Files\Java\jdk1.8.0_211\bin\java.exe" -Dvisualvm.id=443604366717400 "-javaagent:D:\DevelopTools\IDEA\IntelliJ IDEA 2019.2.2\lib\idea_rt.jar=12578:D:\DevelopTools\IDEA\IntelliJ IDEA 2019.2.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_211\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\rt.jar;E:\CODE\Architecture\serializer\target\classes;C:\Users\zwz\.m2\repository\com\thoughtworks\xstream\xstream\1.4.10\xstream-1.4.10.jar;C:\Users\zwz\.m2\repository\xmlpull\xmlpull\1.1.3.1\xmlpull-1.1.3.1.jar;C:\Users\zwz\.m2\repository\xpp3\xpp3_min\1.1.4c\xpp3_min-1.1.4c.jar;C:\Users\zwz\.m2\repository\com\alibaba\fastjson\1.2.31\fastjson-1.2.31.jar;C:\Users\zwz\.m2\repository\io\netty\netty-all\4.1.45.Final\netty-all-4.1.45.Final.jar;C:\Users\zwz\.m2\repository\junit\junit\4.12\junit-4.12.jar;C:\Users\zwz\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;C:\Users\zwz\.m2\repository\com\google\protobuf\protobuf-java\3.7.1\protobuf-java-3.7.1.jar" com.gp.lock.serizlizer.protobuf.Server
msg body len:28
msgbody =���ccf�"�
�chinashenzhen
Receive:
id: 1
name: "ccf"
age: 12
addr {
  contry: "china"
  city: "shenzhen"
}

7.3 protostuff

protostuff是一个基于protobuf实现的序列化方法,它较于protobuf最明显的好处是,在几乎不损耗性能的情况下做到了不用我们写.proto文件来实现序列化。

package com.gp.lock.serizlizer.protobuf;

import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.runtime.RuntimeSchema;

import java.util.ArrayList;
import java.util.List;

public class ProtostuffTest {

    static RuntimeSchema<Po> poSchema = RuntimeSchema.createFrom(Po.class);

    private static byte[] decode(Po po) {
        return ProtostuffIOUtil.toByteArray(po, poSchema, LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));
    }

    private static Po ecode(byte[] bytes) {
        Po po = poSchema.newMessage();
        ProtostuffIOUtil.mergeFrom(bytes, po, poSchema);
        return po;
    }

    public static void main(String[] args) {
        InnerPo innerPo = new InnerPo(1, "InnerPo1");
        List<String> list = new ArrayList<String>();
        list.add("a");
        list.add("b");
        Po po = new Po(1, "Fong", "备注", 24, new int[]{1, 2, 3, 4}, innerPo, list);
        byte[] bytes = decode(po);
        System.out.println(bytes.length);
        Po newPo = ecode(bytes);
        System.out.println(newPo);
    }

}

运行结果

65
id:1
name:Fong
remark:备注
age:24
array:[1, 2, 3, 4]
innerPo:1-InnerPo1
more:[a, b]

模式

package com.asiainfo.dacp.brokerframe.protocol.rpc;

import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtobufIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
import org.objenesis.Objenesis;
import org.objenesis.ObjenesisStd;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @description: Protostuff 序列化与反序列化工具
 * @date : 2020/6/11 17:02
 * @author: zwz
 */
public class SerializationUtil {

    private static Map<Class<?>, Schema<?>> cacheSchema = new ConcurrentHashMap<>();

    private static Objenesis objenesis = new ObjenesisStd(true);

    public SerializationUtil() {
    }

    private static <T> Schema<T> getSchema(Class<T> cls) {
        Schema<T> schema = (Schema<T>) cacheSchema.get(cls);
        if (schema == null) {
            schema = RuntimeSchema.createFrom(cls);
            cacheSchema.put(cls, schema);
        }
        return schema;
    }

    public static <T> byte[] serialize(T obj) {
        Class<T> cls = (Class<T>) obj.getClass();
        LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
        try {
            Schema<T> schema = getSchema(cls);
            //序列化:把 obj 按照 schema 模式 写入到 buffer
            return ProtobufIOUtil.toByteArray(obj, schema, buffer);
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        } finally {
            buffer.clear();
        }
    }

    public static <T> T deserialized(byte[] data, Class<T> cls) {
        try {
            T message = objenesis.newInstance(cls);
            Schema<T> schema = getSchema(cls);
            //反序列化:将 data 按 schema 模式重建实例 message
            ProtobufIOUtil.mergeFrom(data, message, schema);
            return message;
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }
}

7.4 Protocol Buffer 的性能好,主要体现在 序列化后的数据体积小 & 序列化速度快,最终使得传输效率高,其原因如下:

  1. 序列化速度快的原因:
  1. 序列化后的数据量体积小(即数据压缩效果好)的原因:

8. 序列化技术选型

技术层面

  1. 序列化空间开销,也就是序列化产生的结果大小,这个影响到传输的性能

  2. 序列化过程中消耗的时长,序列化消耗时间过长影响到业务的响应时间

  3. 序列化协议是否支持跨平台,跨语言。因为现在的架构更加灵活,如果存在异构系统通信需求,那么这个是必须要考虑的

  4. 可扩展性/兼容性,在实际业务开发中,系统往往需要随着需求的快速迭代来实现快速更新,这就要求我们采用的序列化协议基于良好的可扩展性/兼容性,比如在现有的序列化数据结构中新增一个业务字段,不会影响到现有的服务

  5. 技术的流行程度,越流行的技术意味着使用的公司多,那么很多坑都已经淌过并且得到了解决,技术解决方案也相对成熟

  6. 学习难度和易用性

选型建议

  1. 对性能要求不高的场景,可以采用基于 XML 的 SOAP 协议

  2. 对性能和间接性有比较高要求的场景,那么 Hessian、Protobuf、Thrift、Avro 都可以。

  3. 基于前后端分离,或者独立的对外的 api 服务,选用 JSON 是比较好的,对于调试、可读性都很不错

  4. Avro 设计理念偏于动态类型语言,那么这类的场景使用 Avro 是可以的

上一篇下一篇

猜你喜欢

热点阅读