第 2 章 使用 ProtoStream 实现自定义对象
Marshalling 是一个将 Java 对象转换为可在网络传输或存储到磁盘的二进制格式的进程。反向进程 unmarshalling 将数据从二进制格式转换回 Java 对象。
Data Grid 执行 marshalling 和 unmarshalling to:
- 将数据发送到集群中的其他 Data Grid 节点。
- 将数据存储在持久缓存存储中。
- 在客户端和远程缓存之间传输对象。
- 将对象存储在 JVM 堆之外的原生内存中。
-
当缓存编码不是
application/x-java-object时,将对象存储在 JVM 堆内存中。
在 Data Grid 缓存中存储自定义对象时,您应该使用带有 ProtoStream marshaller 的基于 Protobuf 的 marshalling。
2.1. ProtoStream marshalling 复制链接链接已复制到粘贴板!
Data Grid 提供 ProtoStream API,以便您可以将所有 Java 对象作为协议缓冲器(Protobuf)进行 marshall。
ProtoStream 原生支持许多不同的 Java 数据类型,这意味着您不需要为这些类型配置 ProtoStream marshalling。对于自定义或用户类型,您需要提供一些信息,以便数据网格可以将这些对象划分到缓存中。
SerializationContext-
包含 Protobuf 类型定义的存储库,从 Protobuf 模式(
.proto文件)和附带的 marshallers 加载。 SerializationContextInitializer-
初始化
SerializationContext的接口。
2.1.1. ProtoStream 类型 复制链接链接已复制到粘贴板!
Data Grid 使用了一个 ProtoStream 库,它可以针对键和值处理以下类型,并在原语类型中处理未附带的等效类型:
-
byte[] -
byte -
字符串 -
整数 -
Long -
� -
浮点值 -
布尔值 -
short -
字符 -
java.util.Date -
java.time.Instant
其他类型的集合
ProtoStream 库包括多个用于常见 Java 类型的适配器类,例如:
-
java.math.BigDecimal -
java.math.BigInteger -
java.util.UUID -
java.util.BitSet
Data Grid 为 protostream-types 工件中的一些通用 JDK 类提供所有适配器类,它们包含在 infinispan-core 和 infinispan-client-hotrod 依赖项中。您不需要任何配置将适配器类存储为键或值。
但是,如果要使用适配器类作为 ProtoStream-annotated POJO 中的 marshallable 字段,您可以使用以下方法这样做:
-
使用
ProtoSchema注解的dependentOn元素指定CommonTypesSchema和CommonContainerTypesSchema类。
@ProtoSchema(dependsOn = {org.infinispan.protostream.types.java.CommonTypes, org.infinispan.protostream.types.java.CommonContainerTypes}, schemaFileName = "library.proto", schemaFilePath = "proto", schemaPackageName = "example")
public interface LibraryInitalizer extends SerializationContextInitializer {
}
@ProtoSchema(dependsOn = {org.infinispan.protostream.types.java.CommonTypes, org.infinispan.protostream.types.java.CommonContainerTypes}, schemaFileName = "library.proto", schemaFilePath = "proto", schemaPackageName = "example")
public interface LibraryInitalizer extends SerializationContextInitializer {
}
-
使用
ProtoSchema注解的includeClasses元素指定所需的适配器类
@ProtoSchema(includeClasses = { Author.class, Book.class, UUIDAdapter.class, java.math.BigInteger }, schemaFileName = "library.proto", schemaFilePath = "proto", schemaPackageName = "library")
public interface LibraryInitalizer extends SerializationContextInitializer {
}
@ProtoSchema(includeClasses = { Author.class, Book.class, UUIDAdapter.class, java.math.BigInteger }, schemaFileName = "library.proto", schemaFilePath = "proto", schemaPackageName = "library")
public interface LibraryInitalizer extends SerializationContextInitializer {
}
2.1.2. ProtoStream 注解 复制链接链接已复制到粘贴板!
ProtoStream API 包含您可以添加到 Java 应用程序的注解来定义 Protobuf 模式,后者为对象提供结构化格式。
本主题提供有关 ProtoStream 注解的额外详情。您应该参考 org.infinispan.protostream.annotations 软件包中的文档来获取完整的信息。
Proto
@proto 定义协议缓冲消息,无需使用 注释给所有字段标注。
@Proto Field
- 使用此注解从带有公共字段的记录或类快速生成消息。
- 字段必须是公共的,它们将根据声明顺序分配递增数字。
-
可以使用
ProtoField注解覆盖字段的自动默认值。
使用自动 Protobuf 字段编号只适用于快速原型。对于生产环境,您应该遵循 协议缓冲最佳实践,以确保未来/反馈与您的模式兼容。
ProtoField
@ProtoField 定义 Protobuf message 字段。
此注解适用于字段以及 getter 和 setter 方法。除非使用的是 @Proto 注释,否则类必须至少有一个字段标上 @ProtoField,然后 Data Grid 可以将其 marshall 作为 Protobuf。
| 参数 | value | 可选或必需的 | 描述 |
|---|---|---|---|
|
| 整数 | 必填 | 标签号在类内必须是唯一的。 |
|
| 类型 | 选填 | 声明字段的 Protobuf 类型。如果没有指定类型,则会从 Java 属性中推断出它。
您可以使用 |
|
| 类 | 选填 | 如果属性 type 是接口或抽象类,则指示实际集合类型。 |
|
| 类 | 选填 | 如果属性 type 是抽象类或接口,则表示实际的 Java 类型。该值必须为属性类型分配可即时的 Java 类型。
如果使用 |
|
| 字符串 | 选填 | 指定 Protobuf 模式的名称。 |
|
| 字符串 | 选填 | 如果字段在从缓存中读取时不可用,则指定字段的默认值。该值必须遵循 Java 字段类型的正确语法。 |
ProtoFactory
@ProtoFactory 标记用于创建消息类实例的单个构造器或静态工厂方法。
您可以使用此注解来支持不可变消息类。使用 @ProtoField 注解的所有字段都必须包含在参数中。
-
@ProtoFactory结构或方法的字段名称和参数必须与对应的 Protobuf 消息匹配,但顺序不重要。 -
如果您没有将
@ProtoFactory注解的构造器添加到类,则该类必须具有默认的 no-argument 结构器,否则编译过程中发生错误。
ProtoSchema
@ProtoSchema 生成扩展 SerializationContextInitializer 的类或接口的实施。
如果激活,ProtoStream 处理器会在编译时在带有 Impl 后缀或您使用 className 参数指定的名称相同的软件包中生成实现。
includeClasses 或 basePackages 参数引用 ProtoStream 处理器应扫描并包含在 Protobuf 模式和 marshaller 中的类。如果您没有设置这些参数,ProtoStream 处理器会扫描整个源路径,这可能会导致意外的结果,我们不建议这样做。您还可以使用 excludeClasses 参数和 basePackages 参数来排除类。
schemaFileName 和 schemaPackageName 参数在此名称下注册生成的 Protobuf 模式。如果没有设置这些参数,则注释的简单类名称将与未命名或默认软件包一起使用。模式名称必须以 .proto 文件扩展名结尾。您还可以使用 marshallersOnly 来只生成 marshallers,并阻止 Protobuf 模式生成。
ProtoStream 进程自动生成 META-INF/services 服务元数据文件,您可以使用这些文件以便 Data Grid 服务器自动获取 JAR 来注册 Protobuf 模式。
dependentOn 参数列出了实施 SerializedContextInitializer 的注解类,以首先执行。如果类没有实现 SerializedContextInitializer,或使用 ProtoSchema 注解,则会出现编译时间错误。
ProtoAdapter
@ProtoAdapter 是无法直接注解的类或枚举的 marshalling adapter。
如果您将此注解用于:
-
注解的类必须具有一个
@ProtoFactory注解的 marshalled 类并为每个字段标注的 accessor 方法。这些方法可以是 instance 或 static 方法,其第一个参数必须是 marshalled 类。 - Enums,目标枚举中必须存在相同的命名 enum 值。
ProtoName
@ProtoName 是一个可选注释,用于指定 Protobuf 消息或 enum 类型名称。它可用于类、记录和枚举。
ProtoEnumValue
@ProtoEnumValue 定义 Protobuf enum 值。您只能将此注解应用到 Java enum 的成员。
ProtoReserved 和 ProtoReservedStatements
@ProtoReserved 和 @ProtoReservedStatements 将 保留的 语句添加到生成的消息或枚举定义中,以防止以后使用数字、范围和名称。
ProtoTypeId
@ProtoTypeId (可选)为 Protobuf 消息或 enum 类型指定全局唯一的数字类型标识符。
您不应该将此注解添加到类,因为 Data Grid 在内部使用,标识符可能会在不通知的情况下改变。
ProtoUnknownFieldSet
@ProtoUnknownFieldSet (可选)表示字段或类型为 {@link org.infinispan.protostream.UnknownFieldSet} 的 JavaBean 属性,它存储了任何未知字段。
Data Grid 不推荐使用这个注解,因为它不再被 Google 支持,并可能在以后被删除。
其他注解
Data Grid 将类、字段和方法上的任何其他注解复制为生成的 Protobuf 模式中的注释。这包括索引注释,如 @Indexed 和 @Basic。