You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by al...@apache.org on 2021/09/11 14:01:46 UTC

[dubbo-spi-extensions] branch master updated: Extend avro serialization (#55)

This is an automated email from the ASF dual-hosted git repository.

albumenj pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo-spi-extensions.git


The following commit(s) were added to refs/heads/master by this push:
     new 9c5d9dd  Extend avro serialization (#55)
9c5d9dd is described below

commit 9c5d9dde494b44b3363ebcb8d33e8aa45382d141
Author: clown <32...@users.noreply.github.com>
AuthorDate: Sat Sep 11 22:01:43 2021 +0800

    Extend avro serialization (#55)
    
    avro test
---
 .../{ => dubbo-serialization-avro}/pom.xml         |  30 ++-
 .../common/serialize/avro/AvroObjectInput.java     | 118 ++++++++++++
 .../common/serialize/avro/AvroObjectOutput.java    | 106 +++++++++++
 .../common/serialize/avro/AvroSerialization.java   |  52 ++++++
 ...org.apache.dubbo.common.serialize.Serialization |   1 +
 .../{ => dubbo-serialization-test}/pom.xml         |  28 ++-
 .../serialize/avro/AvroObjectInputOutputTest.java  | 196 ++++++++++++++++++++
 .../serialize/avro/AvroSerializationTest.java      |  64 +++++++
 .../dubbo/common/serialize/model/AnimalEnum.java   |  21 +++
 .../dubbo/common/serialize/model/BizException.java |  29 +++
 .../model/BizExceptionNoDefaultConstructor.java    |  26 +++
 .../dubbo/common/serialize/model/Organization.java |  30 +++
 .../dubbo/common/serialize/model/Person.java       |  95 ++++++++++
 .../common/serialize/model/SerializablePerson.java |  97 ++++++++++
 .../dubbo/common/serialize/model/media/Image.java  | 120 ++++++++++++
 .../dubbo/common/serialize/model/media/Media.java  | 205 ++++++++++++++++++++
 .../common/serialize/model/media/MediaContent.java |  78 ++++++++
 .../common/serialize/model/person/BigPerson.java   | 151 +++++++++++++++
 .../common/serialize/model/person/FullAddress.java | 202 ++++++++++++++++++++
 .../common/serialize/model/person/PersonInfo.java  | 206 +++++++++++++++++++++
 .../serialize/model/person/PersonStatus.java       |  22 +++
 .../dubbo/common/serialize/model/person/Phone.java | 139 ++++++++++++++
 .../support/SerializableClassRegistryTest.java     |  38 ++++
 .../src/test/proto/GooglePB.proto                  |  51 +++++
 .../src/test/resources/log4j.xml}                  |  29 ++-
 .../SimpleDO.fc                                    |   2 +
 dubbo-serialization-extensions/pom.xml             |   7 +-
 27 files changed, 2110 insertions(+), 33 deletions(-)

diff --git a/dubbo-serialization-extensions/pom.xml b/dubbo-serialization-extensions/dubbo-serialization-avro/pom.xml
similarity index 56%
copy from dubbo-serialization-extensions/pom.xml
copy to dubbo-serialization-extensions/dubbo-serialization-avro/pom.xml
index 0b44ebe..1353afe 100644
--- a/dubbo-serialization-extensions/pom.xml
+++ b/dubbo-serialization-extensions/dubbo-serialization-avro/pom.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="UTF-8"?>
 <!--
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
@@ -15,18 +14,31 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.apache.dubbo.extensions</groupId>
-        <artifactId>extensions-parent</artifactId>
+        <artifactId>dubbo-serialization-extensions</artifactId>
         <version>${revision}</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>dubbo-serialization-extensions</artifactId>
-
+    <artifactId>dubbo-serialization-avro</artifactId>
+    <packaging>jar</packaging>
+    <name>${project.artifactId}</name>
+    <description>The avro serialization module of dubbo project</description>
+    <properties>
+        <skip_maven_deploy>false</skip_maven_deploy>
+    </properties>
 
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-serialization-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.avro</groupId>
+            <artifactId>avro</artifactId>
+        </dependency>
+    </dependencies>
 </project>
diff --git a/dubbo-serialization-extensions/dubbo-serialization-avro/src/main/java/org/apache/dubbo/common/serialize/avro/AvroObjectInput.java b/dubbo-serialization-extensions/dubbo-serialization-avro/src/main/java/org/apache/dubbo/common/serialize/avro/AvroObjectInput.java
new file mode 100644
index 0000000..036f5f0
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-avro/src/main/java/org/apache/dubbo/common/serialize/avro/AvroObjectInput.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.avro;
+
+import org.apache.dubbo.common.serialize.ObjectInput;
+
+import org.apache.avro.io.BinaryDecoder;
+import org.apache.avro.io.DecoderFactory;
+import org.apache.avro.reflect.ReflectDatumReader;
+import org.apache.avro.util.Utf8;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Type;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+
+public class AvroObjectInput implements ObjectInput {
+    private static DecoderFactory decoderFactory = DecoderFactory.get();
+    private BinaryDecoder decoder;
+
+    public AvroObjectInput(InputStream in) {
+        decoder = decoderFactory.binaryDecoder(in, null);
+    }
+
+    @Override
+    public boolean readBool() throws IOException {
+        return decoder.readBoolean();
+    }
+
+    @Override
+    public byte readByte() throws IOException {
+        byte[] bytes = new byte[1];
+        decoder.readFixed(bytes);
+        return bytes[0];
+    }
+
+    @Override
+    public short readShort() throws IOException {
+        return (short) decoder.readInt();
+    }
+
+    @Override
+    public int readInt() throws IOException {
+        return decoder.readInt();
+    }
+
+    @Override
+    public long readLong() throws IOException {
+        return decoder.readLong();
+    }
+
+    @Override
+    public float readFloat() throws IOException {
+        return decoder.readFloat();
+    }
+
+    @Override
+    public double readDouble() throws IOException {
+        return decoder.readDouble();
+    }
+
+    @Override
+    public String readUTF() throws IOException {
+        Utf8 result = new Utf8();
+        result = decoder.readString(result);
+        return result.toString();
+    }
+
+    @Override
+    public byte[] readBytes() throws IOException {
+        String resultStr = decoder.readString();
+        return resultStr.getBytes(StandardCharsets.UTF_8);
+    }
+
+    /**
+     * will lost all attribute
+     */
+    @Override
+    public Object readObject() throws IOException, ClassNotFoundException {
+        ReflectDatumReader<Object> reader = new ReflectDatumReader<>(Object.class);
+        return reader.read(null, decoder);
+    }
+
+    @Override
+    @SuppressWarnings(value = {"unchecked"})
+    public <T> T readObject(Class<T> cls) throws IOException, ClassNotFoundException {
+        //Map interface class change to HashMap implement
+        if (cls == Map.class) {
+            cls = (Class<T>) HashMap.class;
+        }
+
+        ReflectDatumReader<T> reader = new ReflectDatumReader<>(cls);
+        return reader.read(null, decoder);
+    }
+
+    @Override
+    public <T> T readObject(Class<T> cls, Type type) throws IOException, ClassNotFoundException {
+        ReflectDatumReader<T> reader = new ReflectDatumReader<>(cls);
+        return reader.read(null, decoder);
+    }
+
+}
diff --git a/dubbo-serialization-extensions/dubbo-serialization-avro/src/main/java/org/apache/dubbo/common/serialize/avro/AvroObjectOutput.java b/dubbo-serialization-extensions/dubbo-serialization-avro/src/main/java/org/apache/dubbo/common/serialize/avro/AvroObjectOutput.java
new file mode 100644
index 0000000..a1f97c3
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-avro/src/main/java/org/apache/dubbo/common/serialize/avro/AvroObjectOutput.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.avro;
+
+import org.apache.dubbo.common.serialize.ObjectOutput;
+
+import org.apache.avro.io.BinaryEncoder;
+import org.apache.avro.io.EncoderFactory;
+import org.apache.avro.reflect.ReflectDatumWriter;
+import org.apache.avro.util.Utf8;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+
+public class AvroObjectOutput implements ObjectOutput {
+    private static EncoderFactory encoderFactory = EncoderFactory.get();
+    private BinaryEncoder encoder;
+
+    public AvroObjectOutput(OutputStream out) {
+        encoder = encoderFactory.binaryEncoder(out, null);
+    }
+
+    @Override
+    public void writeBool(boolean v) throws IOException {
+        encoder.writeBoolean(v);
+    }
+
+    @Override
+    public void writeByte(byte v) throws IOException {
+        encoder.writeFixed(new byte[]{v});
+    }
+
+    @Override
+    public void writeShort(short v) throws IOException {
+        encoder.writeInt(v);
+    }
+
+    @Override
+    public void writeInt(int v) throws IOException {
+        encoder.writeInt(v);
+    }
+
+    @Override
+    public void writeLong(long v) throws IOException {
+        encoder.writeLong(v);
+    }
+
+    @Override
+    public void writeFloat(float v) throws IOException {
+        encoder.writeFloat(v);
+    }
+
+    @Override
+    public void writeDouble(double v) throws IOException {
+        encoder.writeDouble(v);
+    }
+
+    @Override
+    public void writeUTF(String v) throws IOException {
+        encoder.writeString(new Utf8(v));
+    }
+
+    @Override
+    public void writeBytes(byte[] v) throws IOException {
+        encoder.writeString(new String(v, StandardCharsets.UTF_8));
+    }
+
+    @Override
+    public void writeBytes(byte[] v, int off, int len) throws IOException {
+        byte[] v2 = Arrays.copyOfRange(v, off, off + len);
+        encoder.writeString(new String(v2, StandardCharsets.UTF_8));
+    }
+
+    @Override
+    public void flushBuffer() throws IOException {
+        encoder.flush();
+    }
+
+    @Override
+    @SuppressWarnings(value = {"rawtypes", "unchecked"})
+    public void writeObject(Object obj) throws IOException {
+        if (obj == null) {
+            encoder.writeNull();
+            return;
+        }
+        ReflectDatumWriter dd = new ReflectDatumWriter<>(obj.getClass());
+        dd.write(obj, encoder);
+    }
+
+}
diff --git a/dubbo-serialization-extensions/dubbo-serialization-avro/src/main/java/org/apache/dubbo/common/serialize/avro/AvroSerialization.java b/dubbo-serialization-extensions/dubbo-serialization-avro/src/main/java/org/apache/dubbo/common/serialize/avro/AvroSerialization.java
new file mode 100644
index 0000000..e1bc6e8
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-avro/src/main/java/org/apache/dubbo/common/serialize/avro/AvroSerialization.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.avro;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.serialize.ObjectInput;
+import org.apache.dubbo.common.serialize.ObjectOutput;
+import org.apache.dubbo.common.serialize.Serialization;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import static org.apache.dubbo.common.serialize.Constants.AVRO_SERIALIZATION_ID;
+
+public class AvroSerialization implements Serialization {
+
+    @Override
+    public byte getContentTypeId() {
+        return AVRO_SERIALIZATION_ID;
+    }
+
+    @Override
+    public String getContentType() {
+        return "avro/binary";
+    }
+
+    @Override
+    public ObjectOutput serialize(URL url, OutputStream output) throws IOException {
+        return new AvroObjectOutput(output);
+    }
+
+    @Override
+    public ObjectInput deserialize(URL url, InputStream input) throws IOException {
+        return new AvroObjectInput(input);
+    }
+
+}
diff --git a/dubbo-serialization-extensions/dubbo-serialization-avro/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization b/dubbo-serialization-extensions/dubbo-serialization-avro/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization
new file mode 100644
index 0000000..d8cba3e
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-avro/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization
@@ -0,0 +1 @@
+avro=org.apache.dubbo.common.serialize.avro.AvroSerialization
\ No newline at end of file
diff --git a/dubbo-serialization-extensions/pom.xml b/dubbo-serialization-extensions/dubbo-serialization-test/pom.xml
similarity index 51%
copy from dubbo-serialization-extensions/pom.xml
copy to dubbo-serialization-extensions/dubbo-serialization-test/pom.xml
index 0b44ebe..27897e3 100644
--- a/dubbo-serialization-extensions/pom.xml
+++ b/dubbo-serialization-extensions/dubbo-serialization-test/pom.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="UTF-8"?>
 <!--
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
@@ -15,18 +14,33 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
         <groupId>org.apache.dubbo.extensions</groupId>
-        <artifactId>extensions-parent</artifactId>
+        <artifactId>dubbo-serialization-extensions</artifactId>
         <version>${revision}</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
-    <artifactId>dubbo-serialization-extensions</artifactId>
-
+    <artifactId>dubbo-serialization-test</artifactId>
+    <packaging>jar</packaging>
+    <name>${project.artifactId}</name>
+    <description>The test serialization module of dubbo project</description>
+    <properties>
+        <skip_maven_deploy>false</skip_maven_deploy>
+    </properties>
 
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.dubbo.extensions</groupId>
+            <artifactId>dubbo-serialization-avro</artifactId>
+            <version>1.0.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-common</artifactId>
+        </dependency>
+    </dependencies>
 </project>
diff --git a/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/avro/AvroObjectInputOutputTest.java b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/avro/AvroObjectInputOutputTest.java
new file mode 100644
index 0000000..0ef1f3a
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/avro/AvroObjectInputOutputTest.java
@@ -0,0 +1,196 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.avro;
+
+
+import org.apache.dubbo.common.serialize.model.Person;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.core.IsNull.nullValue;
+
+
+public class AvroObjectInputOutputTest {
+    private AvroObjectInput avroObjectInput;
+    private AvroObjectOutput avroObjectOutput;
+
+    private PipedOutputStream pos;
+    private PipedInputStream pis;
+
+    @BeforeEach
+    public void setup() throws IOException {
+        pis = new PipedInputStream();
+        pos = new PipedOutputStream();
+        pis.connect(pos);
+
+        avroObjectOutput = new AvroObjectOutput(pos);
+        avroObjectInput = new AvroObjectInput(pis);
+    }
+
+    @AfterEach
+    public void clean() throws IOException {
+        if (pos != null) {
+            pos.close();
+            pos = null;
+        }
+        if (pis != null) {
+            pis.close();
+            pis = null;
+        }
+    }
+
+    @Test
+    public void testWriteReadBool() throws IOException, InterruptedException {
+        avroObjectOutput.writeBool(true);
+        avroObjectOutput.flushBuffer();
+        pos.close();
+
+        boolean result = avroObjectInput.readBool();
+        assertThat(result, is(true));
+    }
+
+    @Test
+    public void testWriteReadByte() throws IOException {
+        avroObjectOutput.writeByte((byte) 'a');
+        avroObjectOutput.flushBuffer();
+        pos.close();
+
+        Byte result = avroObjectInput.readByte();
+
+        assertThat(result, is((byte) 'a'));
+    }
+
+    @Test
+    public void testWriteReadBytes() throws IOException {
+        avroObjectOutput.writeBytes("123456".getBytes());
+        avroObjectOutput.flushBuffer();
+        pos.close();
+
+        byte[] result = avroObjectInput.readBytes();
+
+        assertThat(result, is("123456".getBytes()));
+    }
+
+    @Test
+    public void testWriteReadShort() throws IOException {
+        avroObjectOutput.writeShort((short) 1);
+        avroObjectOutput.flushBuffer();
+        pos.close();
+
+        short result = avroObjectInput.readShort();
+
+        assertThat(result, is((short) 1));
+    }
+
+    @Test
+    public void testWriteReadInt() throws IOException {
+        avroObjectOutput.writeInt(1);
+        avroObjectOutput.flushBuffer();
+        pos.close();
+
+        Integer result = avroObjectInput.readInt();
+
+        assertThat(result, is(1));
+    }
+
+    @Test
+    public void testReadDouble() throws IOException {
+        avroObjectOutput.writeDouble(3.14d);
+        avroObjectOutput.flushBuffer();
+        pos.close();
+
+        Double result = avroObjectInput.readDouble();
+
+        assertThat(result, is(3.14d));
+    }
+
+    @Test
+    public void testReadLong() throws IOException {
+        avroObjectOutput.writeLong(10L);
+        avroObjectOutput.flushBuffer();
+        pos.close();
+
+        Long result = avroObjectInput.readLong();
+
+        assertThat(result, is(10L));
+    }
+
+    @Test
+    public void testWriteReadFloat() throws IOException {
+        avroObjectOutput.writeFloat(1.66f);
+        avroObjectOutput.flushBuffer();
+        pos.close();
+
+        Float result = avroObjectInput.readFloat();
+
+        assertThat(result, is(1.66F));
+    }
+
+    @Test
+    public void testWriteReadUTF() throws IOException {
+        avroObjectOutput.writeUTF("wording");
+        avroObjectOutput.flushBuffer();
+        pos.close();
+
+        String result = avroObjectInput.readUTF();
+
+        assertThat(result, is("wording"));
+    }
+
+    @Test
+    public void testWriteReadObject() throws IOException, ClassNotFoundException {
+        Person p = new Person();
+        p.setAge(30);
+        p.setName("abc");
+
+        avroObjectOutput.writeObject(p);
+        avroObjectOutput.flushBuffer();
+        pos.close();
+
+        Person result = avroObjectInput.readObject(Person.class);
+
+        assertThat(result, not(nullValue()));
+        assertThat(result.getName(), is("abc"));
+        assertThat(result.getAge(), is(30));
+    }
+
+    @Test
+    public void testWriteReadObjectWithoutClass() throws IOException, ClassNotFoundException {
+        Person p = new Person();
+        p.setAge(30);
+        p.setName("abc");
+
+        avroObjectOutput.writeObject(p);
+        avroObjectOutput.flushBuffer();
+        pos.close();
+
+        //这里会丢失所有信息
+        Object result = avroObjectInput.readObject();
+
+        assertThat(result, not(nullValue()));
+//		assertThat(result.getName(), is("abc"));
+//		assertThat(result.getAge(), is(30));
+    }
+}
diff --git a/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/avro/AvroSerializationTest.java b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/avro/AvroSerializationTest.java
new file mode 100644
index 0000000..b416f7a
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/avro/AvroSerializationTest.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.avro;
+
+import org.apache.dubbo.common.serialize.ObjectInput;
+import org.apache.dubbo.common.serialize.ObjectOutput;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import static org.apache.dubbo.common.serialize.Constants.AVRO_SERIALIZATION_ID;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.mockito.Mockito.mock;
+
+public class AvroSerializationTest {
+    private AvroSerialization avroSerialization;
+
+    @BeforeEach
+    public void setUp() {
+        this.avroSerialization = new AvroSerialization();
+    }
+
+    @Test
+    public void testContentType() {
+        assertThat(avroSerialization.getContentType(), is("avro/binary"));
+    }
+
+    @Test
+    public void testContentTypeId() {
+        assertThat(avroSerialization.getContentTypeId(), is(AVRO_SERIALIZATION_ID));
+    }
+
+    @Test
+    public void testObjectOutput() throws IOException {
+        ObjectOutput objectOutput = avroSerialization.serialize(null, mock(OutputStream.class));
+        assertThat(objectOutput, Matchers.<ObjectOutput>instanceOf(AvroObjectOutput.class));
+    }
+
+    @Test
+    public void testObjectInput() throws IOException {
+        ObjectInput objectInput = avroSerialization.deserialize(null, mock(InputStream.class));
+        assertThat(objectInput, Matchers.<ObjectInput>instanceOf(AvroObjectInput.class));
+    }
+}
diff --git a/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/AnimalEnum.java b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/AnimalEnum.java
new file mode 100644
index 0000000..482337d
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/AnimalEnum.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.model;
+
+public enum AnimalEnum {
+    dog, cat, rat, cow, bull, horse
+}
\ No newline at end of file
diff --git a/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/BizException.java b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/BizException.java
new file mode 100644
index 0000000..96657e7
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/BizException.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.model;
+
+public class BizException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    public BizException(String message) {
+        super(message);
+    }
+
+    public BizException() {
+    }
+}
\ No newline at end of file
diff --git a/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/BizExceptionNoDefaultConstructor.java b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/BizExceptionNoDefaultConstructor.java
new file mode 100644
index 0000000..ab41fd5
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/BizExceptionNoDefaultConstructor.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.model;
+
+public class BizExceptionNoDefaultConstructor extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    public BizExceptionNoDefaultConstructor(String message) {
+        super(message);
+    }
+}
\ No newline at end of file
diff --git a/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/Organization.java b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/Organization.java
new file mode 100644
index 0000000..d36d68e
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/Organization.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.model;
+
+public class Organization<T> {
+
+    private T data;
+
+    public T getData() {
+        return data;
+    }
+
+    public void setData(T data) {
+        this.data = data;
+    }
+}
diff --git a/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/Person.java b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/Person.java
new file mode 100644
index 0000000..5498622
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/Person.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.model;
+
+import java.util.Arrays;
+
+public class Person {
+    byte oneByte = 123;
+    private String name = "name1";
+    private int age = 11;
+
+    private String[] value = {"value1", "value2"};
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public byte getOneByte() {
+        return oneByte;
+    }
+
+    public void setOneByte(byte b) {
+        this.oneByte = b;
+    }
+
+    public int getAge() {
+        return age;
+    }
+
+    public void setAge(int age) {
+        this.age = age;
+    }
+
+    public String[] getValue() {
+        return value;
+    }
+
+    public void setValue(String[] value) {
+        this.value = value;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("Person name(%s) age(%d) byte(%s) [value=%s]", name, age, oneByte, Arrays.toString(value));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + age;
+        result = prime * result + ((name == null) ? 0 : name.hashCode());
+        result = prime * result + Arrays.hashCode(value);
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        Person other = (Person) obj;
+        if (age != other.age)
+            return false;
+        if (name == null) {
+            if (other.name != null)
+                return false;
+        } else if (!name.equals(other.name))
+            return false;
+        if (!Arrays.equals(value, other.value))
+            return false;
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/SerializablePerson.java b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/SerializablePerson.java
new file mode 100644
index 0000000..b5ecad9
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/SerializablePerson.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.model;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+public class SerializablePerson implements Serializable {
+    private static final long serialVersionUID = 1L;
+    byte oneByte = 123;
+    private String name = "name1";
+    private int age = 11;
+
+    private String[] value = {"value1", "value2"};
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public byte getOneByte() {
+        return oneByte;
+    }
+
+    public void setOneByte(byte b) {
+        this.oneByte = b;
+    }
+
+    public int getAge() {
+        return age;
+    }
+
+    public void setAge(int age) {
+        this.age = age;
+    }
+
+    public String[] getValue() {
+        return value;
+    }
+
+    public void setValue(String[] value) {
+        this.value = value;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("Person name(%s) age(%d) byte(%s) [value=%s]", name, age, oneByte, Arrays.toString(value));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + age;
+        result = prime * result + ((name == null) ? 0 : name.hashCode());
+        result = prime * result + Arrays.hashCode(value);
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        SerializablePerson other = (SerializablePerson) obj;
+        if (age != other.age)
+            return false;
+        if (name == null) {
+            if (other.name != null)
+                return false;
+        } else if (!name.equals(other.name))
+            return false;
+        if (!Arrays.equals(value, other.value))
+            return false;
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/media/Image.java b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/media/Image.java
new file mode 100644
index 0000000..da235d2
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/media/Image.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.model.media;
+
+
+public class Image implements java.io.Serializable {
+    private static final long serialVersionUID = 1L;
+    public String uri;
+    public String title;  // Can be null
+    public int width;
+    public int height;
+    public Size size;
+
+    public Image() {
+    }
+
+    public Image(String uri, String title, int width, int height, Size size) {
+        this.height = height;
+        this.title = title;
+        this.uri = uri;
+        this.width = width;
+        this.size = size;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Image image = (Image) o;
+
+        if (height != image.height) return false;
+        if (width != image.width) return false;
+        if (size != image.size) return false;
+        if (title != null ? !title.equals(image.title) : image.title != null) return false;
+        if (uri != null ? !uri.equals(image.uri) : image.uri != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = uri != null ? uri.hashCode() : 0;
+        result = 31 * result + (title != null ? title.hashCode() : 0);
+        result = 31 * result + width;
+        result = 31 * result + height;
+        result = 31 * result + (size != null ? size.hashCode() : 0);
+        return result;
+    }
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("[Image ");
+        sb.append("uri=").append(uri);
+        sb.append(", title=").append(title);
+        sb.append(", width=").append(width);
+        sb.append(", height=").append(height);
+        sb.append(", size=").append(size);
+        sb.append("]");
+        return sb.toString();
+    }
+
+    public String getUri() {
+        return uri;
+    }
+
+    public void setUri(String uri) {
+        this.uri = uri;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public int getWidth() {
+        return width;
+    }
+
+    public void setWidth(int width) {
+        this.width = width;
+    }
+
+    public int getHeight() {
+        return height;
+    }
+
+    public void setHeight(int height) {
+        this.height = height;
+    }
+
+    public Size getSize() {
+        return size;
+    }
+
+    public void setSize(Size size) {
+        this.size = size;
+    }
+
+    public enum Size {
+        SMALL, LARGE
+    }
+}
\ No newline at end of file
diff --git a/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/media/Media.java b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/media/Media.java
new file mode 100644
index 0000000..555f847
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/media/Media.java
@@ -0,0 +1,205 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.model.media;
+
+import java.util.List;
+
+@SuppressWarnings("serial")
+public class Media implements java.io.Serializable {
+    public String uri;
+    public String title;        // Can be unset.
+    public int width;
+    public int height;
+    public String format;
+    public long duration;
+    public long size;
+    public int bitrate;         // Can be unset.
+    public boolean hasBitrate;
+    public List<String> persons;
+    public Player player;
+    public String copyright;    // Can be unset.
+
+    public Media() {
+    }
+
+    public Media(String uri, String title, int width, int height, String format, long duration, long size, int bitrate, boolean hasBitrate, List<String> persons, Player player, String copyright) {
+        this.uri = uri;
+        this.title = title;
+        this.width = width;
+        this.height = height;
+        this.format = format;
+        this.duration = duration;
+        this.size = size;
+        this.bitrate = bitrate;
+        this.hasBitrate = hasBitrate;
+        this.persons = persons;
+        this.player = player;
+        this.copyright = copyright;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Media media = (Media) o;
+
+        if (bitrate != media.bitrate) return false;
+        if (duration != media.duration) return false;
+        if (hasBitrate != media.hasBitrate) return false;
+        if (height != media.height) return false;
+        if (size != media.size) return false;
+        if (width != media.width) return false;
+        if (copyright != null ? !copyright.equals(media.copyright) : media.copyright != null) return false;
+        if (format != null ? !format.equals(media.format) : media.format != null) return false;
+        if (persons != null ? !persons.equals(media.persons) : media.persons != null) return false;
+        if (player != media.player) return false;
+        if (title != null ? !title.equals(media.title) : media.title != null) return false;
+        if (uri != null ? !uri.equals(media.uri) : media.uri != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = uri != null ? uri.hashCode() : 0;
+        result = 31 * result + (title != null ? title.hashCode() : 0);
+        result = 31 * result + width;
+        result = 31 * result + height;
+        result = 31 * result + (format != null ? format.hashCode() : 0);
+        result = 31 * result + (int) (duration ^ (duration >>> 32));
+        result = 31 * result + (int) (size ^ (size >>> 32));
+        result = 31 * result + bitrate;
+        result = 31 * result + (hasBitrate ? 1 : 0);
+        result = 31 * result + (persons != null ? persons.hashCode() : 0);
+        result = 31 * result + (player != null ? player.hashCode() : 0);
+        result = 31 * result + (copyright != null ? copyright.hashCode() : 0);
+        return result;
+    }
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("[Media ");
+        sb.append("uri=").append(uri);
+        sb.append(", title=").append(title);
+        sb.append(", width=").append(width);
+        sb.append(", height=").append(height);
+        sb.append(", format=").append(format);
+        sb.append(", duration=").append(duration);
+        sb.append(", size=").append(size);
+        sb.append(", hasBitrate=").append(hasBitrate);
+        sb.append(", bitrate=").append(String.valueOf(bitrate));
+        sb.append(", persons=").append(persons);
+        sb.append(", player=").append(player);
+        sb.append(", copyright=").append(copyright);
+        sb.append("]");
+        return sb.toString();
+    }
+
+    public String getUri() {
+        return uri;
+    }
+
+    public void setUri(String uri) {
+        this.uri = uri;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public int getWidth() {
+        return width;
+    }
+
+    public void setWidth(int width) {
+        this.width = width;
+    }
+
+    public int getHeight() {
+        return height;
+    }
+
+    public void setHeight(int height) {
+        this.height = height;
+    }
+
+    public String getFormat() {
+        return format;
+    }
+
+    public void setFormat(String format) {
+        this.format = format;
+    }
+
+    public long getDuration() {
+        return duration;
+    }
+
+    public void setDuration(long duration) {
+        this.duration = duration;
+    }
+
+    public long getSize() {
+        return size;
+    }
+
+    public void setSize(long size) {
+        this.size = size;
+    }
+
+    public int getBitrate() {
+        return bitrate;
+    }
+
+    public void setBitrate(int bitrate) {
+        this.bitrate = bitrate;
+        this.hasBitrate = true;
+    }
+
+    public List<String> getPersons() {
+        return persons;
+    }
+
+    public void setPersons(List<String> persons) {
+        this.persons = persons;
+    }
+
+    public Player getPlayer() {
+        return player;
+    }
+
+    public void setPlayer(Player player) {
+        this.player = player;
+    }
+
+    public String getCopyright() {
+        return copyright;
+    }
+
+    public void setCopyright(String copyright) {
+        this.copyright = copyright;
+    }
+
+    public enum Player {
+        JAVA, FLASH
+    }
+}
\ No newline at end of file
diff --git a/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/media/MediaContent.java b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/media/MediaContent.java
new file mode 100644
index 0000000..3b65e99
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/media/MediaContent.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.model.media;
+
+import java.util.List;
+
+@SuppressWarnings("serial")
+public class MediaContent implements java.io.Serializable {
+    public Media media;
+    public List<Image> images;
+
+    public MediaContent() {
+    }
+
+    public MediaContent(Media media, List<Image> images) {
+        this.media = media;
+        this.images = images;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        MediaContent that = (MediaContent) o;
+
+        if (images != null ? !images.equals(that.images) : that.images != null) return false;
+        if (media != null ? !media.equals(that.media) : that.media != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = media != null ? media.hashCode() : 0;
+        result = 31 * result + (images != null ? images.hashCode() : 0);
+        return result;
+    }
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("[MediaContent: ");
+        sb.append("media=").append(media);
+        sb.append(", images=").append(images);
+        sb.append("]");
+        return sb.toString();
+    }
+
+    public Media getMedia() {
+        return media;
+    }
+
+    public void setMedia(Media media) {
+        this.media = media;
+    }
+
+    public List<Image> getImages() {
+        return images;
+    }
+
+    public void setImages(List<Image> images) {
+        this.images = images;
+    }
+}
\ No newline at end of file
diff --git a/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/person/BigPerson.java b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/person/BigPerson.java
new file mode 100644
index 0000000..063f5a9
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/person/BigPerson.java
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.model.person;
+
+import java.io.Serializable;
+
+public class BigPerson implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    String personId;
+
+    String loginName;
+
+    PersonStatus status;
+
+    String email;
+
+    String penName;
+
+    PersonInfo infoProfile;
+
+    public BigPerson() {
+
+    }
+
+    public BigPerson(String id) {
+        this.personId = id;
+    }
+
+    public String getPersonId() {
+        return personId;
+    }
+
+    public void setPersonId(String personId) {
+        this.personId = personId;
+    }
+
+    public PersonInfo getInfoProfile() {
+        return infoProfile;
+    }
+
+    public void setInfoProfile(PersonInfo infoProfile) {
+        this.infoProfile = infoProfile;
+    }
+
+    public String getEmail() {
+        return this.email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public String getLoginName() {
+        return this.loginName;
+    }
+
+    public void setLoginName(String loginName) {
+        this.loginName = loginName;
+    }
+
+    public PersonStatus getStatus() {
+        return this.status;
+    }
+
+    public void setStatus(PersonStatus status) {
+        this.status = status;
+    }
+
+    public String getPenName() {
+        return penName;
+    }
+
+    public void setPenName(String penName) {
+        this.penName = penName;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((email == null) ? 0 : email.hashCode());
+        result = prime * result + ((infoProfile == null) ? 0 : infoProfile.hashCode());
+        result = prime * result + ((loginName == null) ? 0 : loginName.hashCode());
+        result = prime * result + ((penName == null) ? 0 : penName.hashCode());
+        result = prime * result + ((personId == null) ? 0 : personId.hashCode());
+        result = prime * result + ((status == null) ? 0 : status.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        BigPerson other = (BigPerson) obj;
+        if (email == null) {
+            if (other.email != null)
+                return false;
+        } else if (!email.equals(other.email))
+            return false;
+        if (infoProfile == null) {
+            if (other.infoProfile != null)
+                return false;
+        } else if (!infoProfile.equals(other.infoProfile))
+            return false;
+        if (loginName == null) {
+            if (other.loginName != null)
+                return false;
+        } else if (!loginName.equals(other.loginName))
+            return false;
+        if (penName == null) {
+            if (other.penName != null)
+                return false;
+        } else if (!penName.equals(other.penName))
+            return false;
+        if (personId == null) {
+            if (other.personId != null)
+                return false;
+        } else if (!personId.equals(other.personId))
+            return false;
+        if (status != other.status)
+            return false;
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "BigPerson [personId=" + personId + ", loginName=" + loginName + ", status="
+                + status + ", email=" + email + ", penName=" + penName + ", infoProfile="
+                + infoProfile + "]";
+    }
+
+}
\ No newline at end of file
diff --git a/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/person/FullAddress.java b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/person/FullAddress.java
new file mode 100644
index 0000000..4f762cf
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/person/FullAddress.java
@@ -0,0 +1,202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.model.person;
+
+import java.io.Serializable;
+
+public class FullAddress implements Serializable {
+
+    private static final long serialVersionUID = 5163979984269419831L;
+
+    private String countryId;
+
+    private String countryName;
+
+    private String provinceName;
+
+    private String cityId;
+
+    private String cityName;
+
+    private String streetAddress;
+
+    private String zipCode;
+
+    public FullAddress() {
+    }
+
+    public FullAddress(String countryId, String provinceName, String cityId, String streetAddress,
+                       String zipCode) {
+        this.countryId = countryId;
+        this.countryName = countryId;
+        this.provinceName = provinceName;
+        this.cityId = cityId;
+        this.cityName = cityId;
+        this.streetAddress = streetAddress;
+        this.zipCode = zipCode;
+    }
+
+    public FullAddress(String countryId, String countryName, String provinceName, String cityId,
+                       String cityName, String streetAddress, String zipCode) {
+        this.countryId = countryId;
+        this.countryName = countryName;
+        this.provinceName = provinceName;
+        this.cityId = cityId;
+        this.cityName = cityName;
+        this.streetAddress = streetAddress;
+        this.zipCode = zipCode;
+    }
+
+    public String getCountryId() {
+        return countryId;
+    }
+
+    public void setCountryId(String countryId) {
+        this.countryId = countryId;
+    }
+
+    public String getCountryName() {
+        return countryName;
+    }
+
+    public void setCountryName(String countryName) {
+        this.countryName = countryName;
+    }
+
+    public String getProvinceName() {
+        return provinceName;
+    }
+
+    public void setProvinceName(String provinceName) {
+        this.provinceName = provinceName;
+    }
+
+    public String getCityId() {
+        return cityId;
+    }
+
+    public void setCityId(String cityId) {
+        this.cityId = cityId;
+    }
+
+    public String getCityName() {
+        return cityName;
+    }
+
+    public void setCityName(String cityName) {
+        this.cityName = cityName;
+    }
+
+    public String getStreetAddress() {
+        return streetAddress;
+    }
+
+    public void setStreetAddress(String streetAddress) {
+        this.streetAddress = streetAddress;
+    }
+
+    public String getZipCode() {
+        return zipCode;
+    }
+
+    public void setZipCode(String zipCode) {
+        this.zipCode = zipCode;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((cityId == null) ? 0 : cityId.hashCode());
+        result = prime * result + ((cityName == null) ? 0 : cityName.hashCode());
+        result = prime * result + ((countryId == null) ? 0 : countryId.hashCode());
+        result = prime * result + ((countryName == null) ? 0 : countryName.hashCode());
+        result = prime * result + ((provinceName == null) ? 0 : provinceName.hashCode());
+        result = prime * result + ((streetAddress == null) ? 0 : streetAddress.hashCode());
+        result = prime * result + ((zipCode == null) ? 0 : zipCode.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        FullAddress other = (FullAddress) obj;
+        if (cityId == null) {
+            if (other.cityId != null)
+                return false;
+        } else if (!cityId.equals(other.cityId))
+            return false;
+        if (cityName == null) {
+            if (other.cityName != null)
+                return false;
+        } else if (!cityName.equals(other.cityName))
+            return false;
+        if (countryId == null) {
+            if (other.countryId != null)
+                return false;
+        } else if (!countryId.equals(other.countryId))
+            return false;
+        if (countryName == null) {
+            if (other.countryName != null)
+                return false;
+        } else if (!countryName.equals(other.countryName))
+            return false;
+        if (provinceName == null) {
+            if (other.provinceName != null)
+                return false;
+        } else if (!provinceName.equals(other.provinceName))
+            return false;
+        if (streetAddress == null) {
+            if (other.streetAddress != null)
+                return false;
+        } else if (!streetAddress.equals(other.streetAddress))
+            return false;
+        if (zipCode == null) {
+            if (other.zipCode != null)
+                return false;
+        } else if (!zipCode.equals(other.zipCode))
+            return false;
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        if (countryName != null && countryName.length() > 0) {
+            sb.append(countryName);
+        }
+        if (provinceName != null && provinceName.length() > 0) {
+            sb.append(" ");
+            sb.append(provinceName);
+        }
+        if (cityName != null && cityName.length() > 0) {
+            sb.append(" ");
+            sb.append(cityName);
+        }
+        if (streetAddress != null && streetAddress.length() > 0) {
+            sb.append(" ");
+            sb.append(streetAddress);
+        }
+        return sb.toString();
+    }
+
+}
\ No newline at end of file
diff --git a/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/person/PersonInfo.java b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/person/PersonInfo.java
new file mode 100644
index 0000000..5377d77
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/person/PersonInfo.java
@@ -0,0 +1,206 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.model.person;
+
+import java.io.Serializable;
+import java.util.List;
+
+public class PersonInfo implements Serializable {
+    private static final long serialVersionUID = 7443011149612231882L;
+
+    List<Phone> phones;
+
+    Phone fax;
+
+    FullAddress fullAddress;
+
+    String mobileNo;
+
+    String name;
+
+    boolean male;
+
+    boolean female;
+
+    String department;
+
+    String jobTitle;
+
+    String homepageUrl;
+
+    public List<Phone> getPhones() {
+        return phones;
+    }
+
+    public void setPhones(List<Phone> phones) {
+        this.phones = phones;
+    }
+
+    public boolean isMale() {
+        return male;
+    }
+
+    public void setMale(boolean male) {
+        this.male = male;
+    }
+
+    public boolean isFemale() {
+        return female;
+    }
+
+    public void setFemale(boolean female) {
+        this.female = female;
+    }
+
+    public String getDepartment() {
+        return department;
+    }
+
+    public void setDepartment(String department) {
+        this.department = department;
+    }
+
+    public Phone getFax() {
+        return fax;
+    }
+
+    public void setFax(Phone fax) {
+        this.fax = fax;
+    }
+
+    public FullAddress getFullAddress() {
+        return fullAddress;
+    }
+
+    public void setFullAddress(FullAddress fullAddress) {
+        this.fullAddress = fullAddress;
+    }
+
+    public String getHomepageUrl() {
+        return homepageUrl;
+    }
+
+    public void setHomepageUrl(String homepageUrl) {
+        this.homepageUrl = homepageUrl;
+    }
+
+    public String getJobTitle() {
+        return jobTitle;
+    }
+
+    public void setJobTitle(String jobTitle) {
+        this.jobTitle = jobTitle;
+    }
+
+    public String getMobileNo() {
+        return mobileNo;
+    }
+
+    public void setMobileNo(String mobileNo) {
+        this.mobileNo = mobileNo;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((department == null) ? 0 : department.hashCode());
+        result = prime * result + ((fax == null) ? 0 : fax.hashCode());
+        result = prime * result + (female ? 1231 : 1237);
+        result = prime * result + ((fullAddress == null) ? 0 : fullAddress.hashCode());
+        result = prime * result + ((homepageUrl == null) ? 0 : homepageUrl.hashCode());
+        result = prime * result + ((jobTitle == null) ? 0 : jobTitle.hashCode());
+        result = prime * result + (male ? 1231 : 1237);
+        result = prime * result + ((mobileNo == null) ? 0 : mobileNo.hashCode());
+        result = prime * result + ((name == null) ? 0 : name.hashCode());
+        result = prime * result + ((phones == null) ? 0 : phones.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        PersonInfo other = (PersonInfo) obj;
+        if (department == null) {
+            if (other.department != null)
+                return false;
+        } else if (!department.equals(other.department))
+            return false;
+        if (fax == null) {
+            if (other.fax != null)
+                return false;
+        } else if (!fax.equals(other.fax))
+            return false;
+        if (female != other.female)
+            return false;
+        if (fullAddress == null) {
+            if (other.fullAddress != null)
+                return false;
+        } else if (!fullAddress.equals(other.fullAddress))
+            return false;
+        if (homepageUrl == null) {
+            if (other.homepageUrl != null)
+                return false;
+        } else if (!homepageUrl.equals(other.homepageUrl))
+            return false;
+        if (jobTitle == null) {
+            if (other.jobTitle != null)
+                return false;
+        } else if (!jobTitle.equals(other.jobTitle))
+            return false;
+        if (male != other.male)
+            return false;
+        if (mobileNo == null) {
+            if (other.mobileNo != null)
+                return false;
+        } else if (!mobileNo.equals(other.mobileNo))
+            return false;
+        if (name == null) {
+            if (other.name != null)
+                return false;
+        } else if (!name.equals(other.name))
+            return false;
+        if (phones == null) {
+            if (other.phones != null)
+                return false;
+        } else if (!phones.equals(other.phones))
+            return false;
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "PersonInfo [phones=" + phones + ", fax=" + fax + ", fullAddress=" + fullAddress
+                + ", mobileNo=" + mobileNo + ", name=" + name + ", male=" + male + ", female="
+                + female + ", department=" + department + ", jobTitle=" + jobTitle
+                + ", homepageUrl=" + homepageUrl + "]";
+    }
+
+}
diff --git a/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/person/PersonStatus.java b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/person/PersonStatus.java
new file mode 100644
index 0000000..f5ae72c
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/person/PersonStatus.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.model.person;
+
+public enum PersonStatus {
+    ENABLED,
+    DISABLED
+}
\ No newline at end of file
diff --git a/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/person/Phone.java b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/person/Phone.java
new file mode 100644
index 0000000..1822eae
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/model/person/Phone.java
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.model.person;
+
+import java.io.Serializable;
+
+public class Phone implements Serializable {
+
+    private static final long serialVersionUID = 4399060521859707703L;
+
+    private String country;
+
+    private String area;
+
+    private String number;
+
+    private String extensionNumber;
+
+    public Phone() {
+    }
+
+    public Phone(String country, String area, String number, String extensionNumber) {
+        this.country = country;
+        this.area = area;
+        this.number = number;
+        this.extensionNumber = extensionNumber;
+    }
+
+    public String getCountry() {
+        return country;
+    }
+
+    public void setCountry(String country) {
+        this.country = country;
+    }
+
+    public String getArea() {
+        return area;
+    }
+
+    public void setArea(String area) {
+        this.area = area;
+    }
+
+    public String getNumber() {
+        return number;
+    }
+
+    public void setNumber(String number) {
+        this.number = number;
+    }
+
+    public String getExtensionNumber() {
+        return extensionNumber;
+    }
+
+    public void setExtensionNumber(String extensionNumber) {
+        this.extensionNumber = extensionNumber;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((area == null) ? 0 : area.hashCode());
+        result = prime * result + ((country == null) ? 0 : country.hashCode());
+        result = prime * result + ((extensionNumber == null) ? 0 : extensionNumber.hashCode());
+        result = prime * result + ((number == null) ? 0 : number.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        Phone other = (Phone) obj;
+        if (area == null) {
+            if (other.area != null)
+                return false;
+        } else if (!area.equals(other.area))
+            return false;
+        if (country == null) {
+            if (other.country != null)
+                return false;
+        } else if (!country.equals(other.country))
+            return false;
+        if (extensionNumber == null) {
+            if (other.extensionNumber != null)
+                return false;
+        } else if (!extensionNumber.equals(other.extensionNumber))
+            return false;
+        if (number == null) {
+            if (other.number != null)
+                return false;
+        } else if (!number.equals(other.number))
+            return false;
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        if (country != null && country.length() > 0) {
+            sb.append(country);
+            sb.append("-");
+        }
+        if (area != null && area.length() > 0) {
+            sb.append(area);
+            sb.append("-");
+        }
+        if (number != null && number.length() > 0) {
+            sb.append(number);
+        }
+        if (extensionNumber != null && extensionNumber.length() > 0) {
+            sb.append("-");
+            sb.append(extensionNumber);
+        }
+        return sb.toString();
+    }
+
+}
\ No newline at end of file
diff --git a/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/support/SerializableClassRegistryTest.java b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/support/SerializableClassRegistryTest.java
new file mode 100644
index 0000000..bba2043
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/support/SerializableClassRegistryTest.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.support;
+
+import org.apache.dubbo.common.serialize.model.SerializablePerson;
+import org.apache.dubbo.common.serialize.model.person.Phone;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Map;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+
+public class SerializableClassRegistryTest {
+    @Test
+    public void testAddClasses() {
+        SerializableClassRegistry.registerClass(SerializablePerson.class);
+        SerializableClassRegistry.registerClass(Phone.class);
+
+        Map<Class<?>, Object> registeredClasses = SerializableClassRegistry.getRegisteredClasses();
+        assertThat(registeredClasses.size(), equalTo(2));
+    }
+}
\ No newline at end of file
diff --git a/dubbo-serialization-extensions/dubbo-serialization-test/src/test/proto/GooglePB.proto b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/proto/GooglePB.proto
new file mode 100644
index 0000000..bda3e37
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/proto/GooglePB.proto
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+syntax = "proto2";
+
+package org.apache.dubbo.common.serialize.protobuf.model;
+
+message PBRequestType {
+    optional double money = 1;
+    optional float cash = 2;
+    optional int32 age = 3;
+    optional int64 num = 4;
+    optional bool sex = 5;
+    optional string name = 6;
+    optional bytes msg = 7;
+    repeated org.apache.dubbo.common.serialize.protobuf.model.PhoneNumber phone = 8;
+    map<string, PhoneNumber> doubleMap = 9;
+}
+
+message PBResponseType {
+    optional string msg = 1;
+    optional org.apache.dubbo.common.serialize.protobuf.model.PBRequestType CDubboPBRequestType = 3;
+}
+
+message PhoneNumber {
+    required string number = 1;
+    optional org.apache.dubbo.common.serialize.protobuf.model.PhoneType type = 2 [default = HOME];
+}
+
+enum PhoneType {
+    MOBILE = 0;
+    HOME = 1;
+    WORK = 2;
+}
+
+service CDubboPBService {
+    rpc sayHello (org.apache.dubbo.common.serialize.protobuf.model.PBRequestType) returns (org.apache.dubbo.common.serialize.protobuf.model.PBResponseType);
+}
\ No newline at end of file
diff --git a/dubbo-serialization-extensions/pom.xml b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/resources/log4j.xml
similarity index 59%
copy from dubbo-serialization-extensions/pom.xml
copy to dubbo-serialization-extensions/dubbo-serialization-test/src/test/resources/log4j.xml
index 0b44ebe..3c5e376 100644
--- a/dubbo-serialization-extensions/pom.xml
+++ b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/resources/log4j.xml
@@ -15,18 +15,17 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <groupId>org.apache.dubbo.extensions</groupId>
-        <artifactId>extensions-parent</artifactId>
-        <version>${revision}</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>dubbo-serialization-extensions</artifactId>
-
-
-</project>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+    <appender name="dubbo" class="org.apache.dubbo.common.utils.DubboAppender">
+        <param name="File" value="../../dubbo.log"/>
+        <param name="encoding" value="GBK"/>
+        <layout class="org.apache.log4j.PatternLayout">
+            <param name="ConversionPattern" value="%d %p [%c:%M] - %m%n"/>
+        </layout>
+    </appender>
+    <root>
+        <level value="INFO"/>
+        <appender-ref ref="dubbo"/>
+    </root>
+</log4j:configuration>
\ No newline at end of file
diff --git a/dubbo-serialization-extensions/dubbo-serialization-test/src/test/resources/org.apache.dubbo.common.serialize.dubbo/SimpleDO.fc b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/resources/org.apache.dubbo.common.serialize.dubbo/SimpleDO.fc
new file mode 100644
index 0000000..c8c083c
--- /dev/null
+++ b/dubbo-serialization-extensions/dubbo-serialization-test/src/test/resources/org.apache.dubbo.common.serialize.dubbo/SimpleDO.fc
@@ -0,0 +1,2 @@
+a,d,e,b,c
+str3,str2
\ No newline at end of file
diff --git a/dubbo-serialization-extensions/pom.xml b/dubbo-serialization-extensions/pom.xml
index 0b44ebe..b80a464 100644
--- a/dubbo-serialization-extensions/pom.xml
+++ b/dubbo-serialization-extensions/pom.xml
@@ -25,8 +25,11 @@
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-
+    <packaging>pom</packaging>
     <artifactId>dubbo-serialization-extensions</artifactId>
 
-
+    <modules>
+        <module>dubbo-serialization-avro</module>
+        <module>dubbo-serialization-test</module>
+    </modules>
 </project>