Codec
Spring Integration 的版本 4.2 引入了 Codec
抽象。编解码器对对象进行编码和解码,使其可以进入和离开 byte[]
。它们为 Java 序列化提供了一种替代方式。一个优点是,通常不需要对象实现 Serializable
。我们提供了一个实现,它使用 Kryo 进行序列化,但是你可以在任何以下组件中提供自己的实现:
-
EncodingPayloadTransformer
-
DecodingTransformer
-
CodecMessageConverter
EncodingPayloadTransformer
此变换器通过使用编解码器将有效负载编码到 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
第一个可与 PojoCodec
一起使用,方法是用 FileKryoRegistrar
对其进行初始化。第二个和第三个与 MessageCodec
一起使用,后者是用 MessageKryoRegistrar
初始化的。
Customizing 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 documentation 中所述。
注册自定义序列化器时,需要注册 ID。注册 ID 是任意的。然而,在我们的案例中,ID 必须被明确定义,因为整个分布式应用程序中的每个 Kryo 实例都必须使用相同的 ID。Kryo 推荐使用小的正整数,并保留一些 ID(值 < 10)。Spring Integration 当前默认使用 40、41 和 42(用于前面提到的文件和消息头序列化器)。我们建议您从 60 开始,以允许框架进行扩展。您可以通过配置前面提到的注册器来覆盖这些框架默认值。 |
Using a Custom Kryo Serializer
如果您需要自定义序列化,请查看 Kryo文档,因为您需要使用本机 API 来执行自定义。例如,请查看 `org.springframework.integration.codec.kryo.MessageCodec`实现。
Implementing KryoSerializable
如果您有对域对象源代码的 write
访问权限,则可以按 here 中所述实现 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 之外的序列化库。
Using the @DefaultSerializer
Annotation
Kryo 还提供了一个 @DefaultSerializer
批注,如 here 中所述。
@DefaultSerializer(SomeClassSerializer.class)
public class SomeClass {
// ...
}
如果您有权“写入”域对象,这可能是指定自定义序列化程序更简单的方法。请注意,这不会使用 ID 注册类,这对于某些情况可能没有帮助。