编解码器
Spring Integration 的 4.2 版本引入了 `Codec` 抽象。编解码器(Codec)用于将对象编码为 `byte[]` 并从 `byte[]` 解码对象。它们提供了 Java 序列化的替代方案。一个优势是,通常对象不需要实现 `Serializable` 接口。我们提供了一个使用 Kryo 进行序列化的实现,但您可以提供自己的实现,用于以下任何组件:
-
EncodingPayloadTransformer
-
DecodingTransformer
-
CodecMessageConverter
`EncodingPayloadTransformer`
此转换器使用编解码器将 payload 编码为 `byte[]`。它不影响消息头。
有关更多信息,请参阅 Javadoc。
`DecodingTransformer`
此转换器使用编解码器解码 `byte[]`。需要配置对象应解码到的 `Class`(或解析为 `Class` 的表达式)。如果结果对象是 `Message>`,则入站头不会被保留。
有关更多信息,请参阅 Javadoc。
`CodecMessageConverter`
某些端点(如 TCP 和 Redis)没有消息头的概念。它们支持使用 `MessageConverter`,而 `CodecMessageConverter` 可以用于将消息转换为 `byte[]` 或从 `byte[]` 转换回消息进行传输。
有关更多信息,请参阅 Javadoc。
Kryo
目前,这是 `Codec` 的唯一实现,它提供了两种 `Codec`:
-
`PojoCodec`:在转换器中使用
-
`MessageCodec`:在 `CodecMessageConverter` 中使用
框架提供了几种自定义序列化器:
-
FileSerializer
-
MessageHeadersSerializer
-
MutableMessageHeadersSerializer
第一个可以通过使用 `FileKryoRegistrar` 初始化 `PojoCodec` 来使用。第二个和第三个与 `MessageCodec` 一起使用,`MessageCodec` 使用 `MessageKryoRegistrar` 进行初始化。
自定义 Kryo
默认情况下,Kryo 将未知 Java 类型委托给其 `FieldSerializer`。Kryo 还为每种基本类型以及 `String`、`Collection` 和 `Map` 注册默认序列化器。`FieldSerializer` 使用反射遍历对象图。更有效的方法是实现一个自定义序列化器,该序列化器了解对象的结构并可以直接序列化选定的基本字段。以下示例展示了这样的序列化器:
public class AddressSerializer extends Serializer<Address> {
@Override
public void write(Kryo kryo, Output output, Address address) {
output.writeString(address.getStreet());
output.writeString(address.getCity());
output.writeString(address.getCountry());
}
@Override
public Address read(Kryo kryo, Input input, Class<Address> type) {
return new Address(input.readString(), input.readString(), input.readString());
}
}
`Serializer` 接口暴露了 `Kryo`、`Input` 和 `Output`,它们提供了对包含哪些字段以及其他内部设置的完全控制,如 Kryo 文档中所述。
注册自定义序列化器时,需要一个注册 ID。注册 ID 是任意的。但是,在我们的情况下,ID 必须明确定义,因为分布式应用程序中的每个 Kryo 实例都必须使用相同的 ID。Kryo 建议使用小的正整数,并保留一些 ID(值 < 10)。Spring Integration 当前默认使用 40、41 和 42(用于前面提到的文件和消息头序列化器)。我们建议您从 60 开始,以便框架未来扩展。您可以通过配置前面提到的注册器来覆盖这些框架默认值。 |
使用自定义 Kryo 序列化器
如果您需要自定义序列化,请参阅 Kryo 文档,因为您需要使用原生 API 进行自定义。例如,请参阅 `org.springframework.integration.codec.kryo.MessageCodec` 的实现。
实现 KryoSerializable
如果您有对域对象源代码的 `write` 访问权限,可以按照此处所述实现 `KryoSerializable`。在这种情况下,类本身提供序列化方法,无需进一步配置。然而,基准测试表明,这不如明确注册自定义序列化器那样高效。以下示例展示了一个自定义 Kryo 序列化器:
public class Address implements KryoSerializable {
@Override
public void write(Kryo kryo, Output output) {
output.writeString(this.street);
output.writeString(this.city);
output.writeString(this.country);
}
@Override
public void read(Kryo kryo, Input input) {
this.street = input.readString();
this.city = input.readString();
this.country = input.readString();
}
}
您也可以使用此技术来包装 Kryo 以外的序列化库。
使用 `@DefaultSerializer` 注解
Kryo 还提供了一个 `@DefaultSerializer` 注解,如此处所述。
@DefaultSerializer(SomeClassSerializer.class)
public class SomeClass {
// ...
}
如果您对域对象有 `write` 访问权限,这可能是指定自定义序列化器的一种更简单的方法。请注意,这不会使用 ID 注册类,这可能导致此技术在某些情况下不太有用。