EBEasyBuild Docs
文档/后端/Fory 序列化

easyfk-fory Fory 序列化

Fory 序列化 — 高性能对象序列化框架阅读时间 ~15 min

1. 模块概述

serializer-fory 是 EasyFK 框架的高性能序列化模块,基于 [Apache Fory](https://fury.apache.org/)(原 Fury)0.14.1 构建。提供 Java 内部序列化和跨语言(XLANG)序列化两种模式,通过 Spring Boot 自动配置实现类的自动扫描与注册,开箱即用。

本模块由两个子模块组成:

  • **serializer-base**:序列化器的抽象层,定义 SPI 接口、配置属性和初始化流程
  • **serializer-fory**:基于 Apache Fory 的具体实现

2. 依赖关系

2.1 serializer-base

groovy
// 父级 build.gradle 声明了 easyfk-core 为所有子模块的编译期依赖
subprojects {
    dependencies {
        compileOnly project(':easyfk-core')
    }
}

2.2 serializer-fory

groovy
dependencies {
    api project(':easyfk-serializer:serializer-base')
    api 'org.apache.fory:fory-core:0.14.1'
}
`easyfk-core`提供 `@SerializableClass` 注解和 `EmptyUtil` 工具
`fory-core 0.14.1`Apache Fory 序列化框架核心库

3. 包结构

plaintext
easyfk-serializer/
├── serializer-base/                          # 抽象层
│   ├── build.gradle                          # (空,继承父级配置)
│   └── src/main/java/com/mcst/easyfk/serializer/base/
│       ├── SerializerClassRegister.java       # SPI 接口:类注册器
│       ├── properties/
│       │   └── SerializerProperties.java      # 配置属性
│       ├── config/
│       │   └── SerializerAutoConfiguration.java # 自动配置
│       └── init/
│           └── SerializerInitializer.java     # 初始化器:扫描+注册
│
└── serializer-fory/                          # Fory 实现层
    ├── build.gradle
    └── src/main/java/com/mcst/easyfk/serializer/fory/
        ├── ForySerializer.java                # 核心:Fory 序列化工具类
        ├── ForySerializerClassRegister.java   # SPI 实现:Fory 类注册器
        └── config/
            └── ForySerializerAutoConfiguration.java # Fory 自动配置

4. 核心接口

4.1 SerializerClassRegister(SPI 接口)

java
public interface SerializerClassRegister {
    default void registerClass(List<Class<?>> classes) {
    }
}

序列化类注册器的函数接口。实现此接口可将扫描到的类注册到具体的序列化器中。模块通过 Spring 容器自动发现所有实现者。

方法说明:

4.2 @SerializableClass(标记注解)

定义在 easyfk-core 模块中:

java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SerializableClass {
}

标记需要预注册到序列化器的类。启动时 SerializerInitializer 会扫描带有此注解的类并交给注册器处理。

5. 配置属性

5.1 SerializerProperties

配置前缀:easyfk.config.serializer

`pre-register`Boolean`true`是否在启动时预注册序列化类。关闭后使用时动态注册
`scan-packages`List&lt;String&gt;`[]`额外需要扫描的包路径列表(默认必扫 `com.mcst`)

5.2 配置示例

yaml
easyfk:
  config:
    serializer:
      pre-register: true
      cross-language: false
      scan-packages:
        - com.example.dto
        - com.example.entity

6. 自动配置

6.1 SerializerAutoConfiguration(serializer-base)

java
@AutoConfiguration
@EnableConfigurationProperties(SerializerProperties.class)
@ConditionalOnProperty(prefix = "easyfk.config.serializer", name = "pre-register",
                       havingValue = "true", matchIfMissing = true)
public class SerializerAutoConfiguration {

    @Bean
    public SerializerInitializer serializerInitializer() {
        return new SerializerInitializer();
    }
}

生效条件: pre-registertrue(默认生效)

注册 SerializerInitializer Bean,负责启动时扫描和注册类。

6.2 ForySerializerAutoConfiguration(serializer-fory)

java
@AutoConfiguration
@ConditionalOnProperty(prefix = "easyfk.config.serializer", name = "pre-register",
                       havingValue = "true", matchIfMissing = true)
public class ForySerializerAutoConfiguration {

    @Bean
    public ForySerializerClassRegister forySerializerClassRegister() {
        return new ForySerializerClassRegister();
    }
}

生效条件: pre-registertrue(默认生效)

注册 ForySerializerClassRegister Bean,使 SerializerInitializer 能够自动发现并调用。

6.3 Spring Boot 自动配置注册

serializer-base:

plaintext
# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.mcst.easyfk.serializer.base.config.SerializerAutoConfiguration

serializer-fory:

plaintext
# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.mcst.easyfk.serializer.fory.config.ForySerializerAutoConfiguration

7. 初始化流程

7.1 SerializerInitializer

SerializerInitializer 实现 InitializingBean,在 Bean 初始化完成后自动执行:

plaintext
Spring 容器启动
    │
    ├─ SerializerAutoConfiguration 注册 SerializerInitializer
    ├─ ForySerializerAutoConfiguration 注册 ForySerializerClassRegister
    │
    └─ afterPropertiesSet() 触发
        │
        ├─ 检查 preRegister 开关
        │   └─ false → 跳过,日志提示
        │
        ├─ 发现所有 SerializerClassRegister Bean
        │   └─ 空 → 跳过
        │
        ├─ 构建 ClassPath 扫描器
        │   └─ 过滤器:@SerializableClass 注解
        │
        ├─ 合并扫描包路径
        │   ├─ 固定包:"com.mcst"
        │   └─ 配置包:scanPackages
        │
        ├─ 扫描所有候选类
        │   └─ ClassPathScanningCandidateComponentProvider
        │       └─ AnnotationTypeFilter(SerializableClass.class)
        │
        └─ 调用所有注册器
            └─ serializerClassRegister.registerClass(classes)
                └─ ForySerializerClassRegister
                    └─ ForySerializer.register(clazz) × N

8. ForySerializer 核心 API

ForySerializer 是序列化操作的入口,提供静态方法调用。

8.1 Java 序列化

java
// 序列化
byte[] data = ForySerializer.serialize(myObject);

// 反序列化
MyClass obj = ForySerializer.deserialize(data);
`serialize(Object obj)`待序列化对象`byte[]`null 返回空数组

8.2 跨语言序列化

需要先开启 cross-language: true 配置:

java
// 跨语言序列化
byte[] data = ForySerializer.serializeXLang(myObject);

// 跨语言反序列化
MyClass obj = ForySerializer.deserializeXLang(data);
`serializeXLang(Object obj)`待序列化对象`byte[]`未开启跨语言时抛 UnsupportedOperationException

8.3 手动注册类

java
ForySerializer.register(MyClass.class);
  • 重复注册会被自动忽略(ConcurrentHashMap.newKeySet 去重)
  • 同时注册到 Java 实例和 XLANG 实例(若已启用)

8.4 获取底层 Fory 实例

java
ThreadSafeFory javaFory = ForySerializer.getJavaFory();
ThreadSafeFory xlangFory = ForySerializer.getXLangFory();

用于需要直接操作 Fory API 的高级场景。

9. ForySerializerClassRegister

SPI 接口的 Fory 实现:

java
public class ForySerializerClassRegister implements SerializerClassRegister {

    @Override
    public void registerClass(List<Class<?>> classes) {
        for (Class<?> clazz : classes) {
            ForySerializer.register(clazz);
        }
    }
}

作为桥梁,将 SerializerInitializer 扫描到的类列表注册到 ForySerializer

10. 快速接入

10.1 添加依赖

groovy
dependencies {
    implementation project(':easyfk-serializer:serializer-fory')
}

10.2 标记序列化类

java
import com.mcst.easyfk.core.annotation.SerializableClass;

@SerializableClass
public class UserDto {
    private String name;
    private int age;
    // getter/setter
}

10.3 使用序列化

java
// 序列化
UserDto user = new UserDto();
user.setName("张三");
user.setAge(25);
byte[] bytes = ForySerializer.serialize(user);

// 反序列化
UserDto restored = ForySerializer.deserialize(bytes);

10.4 启用跨语言模式

yaml
easyfk:
  config:
    serializer:
      cross-language: true
java
byte[] xlangData = ForySerializer.serializeXLang(user);
// 发送 xlangData 到 Python / Go / JavaScript 等语言的 Fory 客户端

10.5 动态注册模式

关闭预注册后,类在首次序列化时自动注册:

yaml
easyfk:
  config:
    serializer:
      pre-register: false

无需 @SerializableClass 注解,但首次序列化会有微小的注册开销。

easyfk-fory — 高性能序列化框架,加速数据传输与存储。

— END —