dubbo 是支持多种序列化方式的,那么它就必须在此基础上做一层封装,来统一序列化层的接口.
现在我们拿 Java 中的序列化来讲解 dubbo 是如何进行封装的.
如果使用 java 序列化,需要做那几步了?
1.实现 java.io.Serializable
2.new ObjectOutputStream,并调用 writeObject 方法写对象
反序列化:
1.new ObjectInputStream
2.调用 readObject 方法读对象.
那么现在 dubbo 需要在此基础上,可以自由使用多种序列化方式,该如何做了?
1.是不是需要一个类似 ObjectOutputStream 和 ObjectInputStream 的角色?是的,在 dubbo 中,它们的名字是DataInput 和 DataOutput
2.光有上面的那两个工具没用呀,需要一个统一多种序列化方式的入口,所以还得一个 Serialization.
3.虽然 dubbo 支持多种序列化方式,那么到底支持哪些了?这些是不是得有一个地方存我支持哪些序列化方式了?确实,在 Constants 中.
4.我们需要对对象序列化的支持,而上面的 DataInput 和 DataOutput 只是对某个值的序列化和反序列化,所以在此基础上,我们需要 ObjectInput 和 ObjectOutput.
5.我们在想远一点,就拿 MySQL 来说吧,每次执行 sql 的时候,会有一个优化器,帮你做出选择,怎么支持会快. 那么序列化是不是也可以这么干了?所以就会有一个 SerializationOptimizer.
6.SerializationOptimizer 中返回的列表会注册到 SerializableClassRegistry 中. 按我的理解,应该是对某些类进行优化序列化吧.
下面来分析下具体的序列化是如何做的,上面只是为统一序列化定义的统一接口.
换句话说,如果我们要自己定义一个序列化方式,应该如何做?
1.实现 Serialization
2.实现 ObjectInput & ObjectOutput
具体看下吧:
这个类很简单,算是入口吧.
public class NativeJavaSerialization implements Serialization {
@Override
public byte getContentTypeId() {
return NATIVE_JAVA_SERIALIZATION_ID;
}
@Override
public String getContentType() {
return "x-application/nativejava";
}
@Override
public ObjectOutput serialize(URL url, OutputStream output) throws IOException {
return new NativeJavaObjectOutput(output);
}
@Override
public ObjectInput deserialize(URL url, InputStream input) throws IOException {
return new NativeJavaObjectInput(input);
}
}
我们看下 ObjectInput & ObjectOutput.
我们可以看到 NativeJavaObjectInput 只是对 ObjectInputStream 的简单封装,NativeJavaObjectOutput 只是对 ObjectOutputStream 的简单封装.
我们再看下 JavaSerialization.
JavaObjectInput 是在 NativeJavaObjectInput 之上构建的,区别是 JavaObjectInput 加入了对空值的判断.
接着看下 CompactedJavaSerialization
CompactedJavaSerialization 的使用场景不了解,暂时不管了.
我也看了下 hessian2 的实现,发现和 JDK 中的实现类似,都是对具体实现的封装,例如 hessian2 是对 Hessian2Input 的封装.