在 《Dubbo 开发指南 —— 序列化扩展.》 ,对序列化定义如下:
将对象转成字节流,用于网络传输,以及将字节流转为对象,用于在收到字节流数据后还原成对象。
API 接口,类图如下:
/**
* Serialization. (SPI, Singleton, ThreadSafe)
*
* 序列化接口
*/
@SPI("hessian2")
public interface Serialization {
/**
* get content type id
*
* 获得内容类型编号
*
* @return content type id
*/
byte getContentTypeId();
/**
* get content type
*
* 获得内容类型名
*
* @return content type
*/
String getContentType();
/**
* create serializer
*
* 创建 ObjectOutput 对象,序列化输出到 OutputStream
*
* @param url URL
* @param output 输出流
* @return serializer
* @throws IOException 当发生 IO 异常时
*/
@Adaptive
ObjectOutput serialize(URL url, OutputStream output) throws IOException;
/**
* create deserializer
*
* 创建 ObjectInput 对象,从 InputStream 反序列化
*
* @param url URL
* @param input 输入流
* @return deserializer
* @throws IOException 当发生 IO 异常时
*/
@Adaptive
ObjectInput deserialize(URL url, InputStream input) throws IOException;
}
数据输入接口。方法如下:
boolean readBool() throws IOException;
byte readByte() throws IOException;
short readShort() throws IOException;
int readInt() throws IOException;
long readLong() throws IOException;
float readFloat() throws IOException;
double readDouble() throws IOException;
String readUTF() throws IOException;
byte[] readBytes() throws IOException;
实现 DataInput 接口,对象输入接口。方法如下:
Object readObject() throws IOException, ClassNotFoundException;
T readObject(Class cls) throws IOException, ClassNotFoundException;
T readObject(Class cls, Type type) throws IOException, ClassNotFoundException;
数据输出接口。方法如下:
void writeBool(boolean v) throws IOException;
void writeByte(byte v) throws IOException;
void writeShort(short v) throws IOException;
void writeInt(int v) throws IOException;
void writeLong(long v) throws IOException;
void writeFloat(float v) throws IOException;
void writeDouble(double v) throws IOException;
void writeUTF(String v) throws IOException;
void writeBytes(byte[] v) throws IOException;
void writeBytes(byte[] v, int off, int len) throws IOException;
// Flush buffer.
void flushBuffer() throws IOException;
实现 DataOutput 接口,对象输出接口。方法如下:
void writeObject(Object obj) throws IOException;
清理接口。方法如下:
void cleanup();
序列化优化器接口。方法如下:
public interface SerializationOptimizer {
/**
* @return 需要使用优化的类的集合
*/
Collection getSerializableClasses();
}
序列化优化类的注册表。代码如下:
public abstract class SerializableClassRegistry {
private static final Set registrations = new LinkedHashSet();
/**
* only supposed to be called at startup time
*/
public static void registerClass(Class clazz) {
registrations.add(clazz);
}
public static Set getRegisteredClasses() {
return registrations;
}
}
在 DubboProtocol#optimizeSerialization() 方法中,初始化序列化优化器。代码如下:
/**
* 已初始化的 SerializationOptimizer 实现类名的集合
*/
private final Set optimizers = new ConcurrentHashSet();
private void optimizeSerialization(URL url) throws RpcException {
// 获得 `"optimizer"` 配置项
String className = url.getParameter(Constants.OPTIMIZER_KEY, "");
if (StringUtils.isEmpty(className) || optimizers.contains(className)) { // 已注册
return;
}
logger.info("Optimizing the serialization process for Kryo, FST, etc...");
try {
// 加载 SerializationOptimizer 实现类
Class clazz = Thread.currentThread().getContextClassLoader().loadClass(className);
if (!SerializationOptimizer.class.isAssignableFrom(clazz)) {
throw new RpcException("The serialization optimizer " + className + " isn't an instance of " + SerializationOptimizer.class.getName());
}
// 创建 SerializationOptimizer 对象
SerializationOptimizer optimizer = (SerializationOptimizer) clazz.newInstance();
if (optimizer.getSerializableClasses() == null) {
return;
}
// 注册到 SerializableClassRegistry 中
for (Class c : optimizer.getSerializableClasses()) {
SerializableClassRegistry.registerClass(c);
}
// 添加到 optimizers 中
optimizers.add(className);
} catch (ClassNotFoundException e) {
throw new RpcException("Cannot find the serialization optimizer class: " + className, e);
} catch (InstantiationException e) {
throw new RpcException("Cannot instantiate the serialization optimizer class: " + className, e);
} catch (IllegalAccessException e) {
throw new RpcException("Cannot instantiate the serialization optimizer class: " + className, e);
}
}