|
如需使用最新稳定版本,请使用 Spring Integration 7.0.4! |
编解码器
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 初始化。
自定义 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,因此该技术在某些情况下可能没有帮助。