You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Quarkus扩展构建阶段解析Executor实例后序列化保存方案咨询

解决方案:Quarkus构建阶段保存Executor实例的两种原生方式

方案一:字节码生成(推荐,Quarkus原生风格)

这是Quarkus扩展最常用的实现思路,完全规避序列化环节,直接在构建阶段生成能返回预构建Executor实例的Java类,运行时直接调用即可。Quarkus本身依赖ByteBuddy,无需额外引入第三方依赖。

实现步骤

  1. 在BuildStep中生成字节码类
    用ByteBuddy生成一个包含静态方法的类,该方法直接返回你解析好的Executor实例:
    @BuildStep
    void generateExecutorProvider(BuildProducer<BytecodeGeneratedClassBuildItem> producer) {
        // executor为解析文本后得到的根Executor实例
        Executor executor = parseTextFileToExecutor();
    
        // 生成类:com.yourpackage.GeneratedExecutorProvider
        DynamicType.Unloaded<?> unloadedClass = new ByteBuddy()
                .subclass(Object.class)
                .name("com.yourpackage.GeneratedExecutorProvider")
                .defineMethod("getExecutor", Executor.class, Modifier.PUBLIC | Modifier.STATIC)
                .intercept(FixedValue.value(executor))
                .make();
    
        // 将生成的类注册到Quarkus构建流程
        producer.produce(BytecodeGeneratedClassBuildItem.builder(unloadedClass)
                .setContextClass(YourExtensionProcessor.class)
                .build());
    }
    
  2. 运行时获取Executor实例
    直接通过静态方法调用,或者用Arc的生产者注入:
    @ApplicationScoped
    public class ExecutorProducer {
        @Produces
        public Executor getExecutor() {
            return com.yourpackage.GeneratedExecutorProvider.getExecutor();
        }
    }
    

方案二:Java原生序列化 + GeneratedResourceBuildItem

如果你的Executor及其所有子类都能实现java.io.Serializable,可以采用这种方式,同样无需额外依赖。

实现步骤

  1. 确保所有Executor类实现Serializable
    给每个Executor子类添加Serializable接口,并显式声明serialVersionUID:
    public class StringExecutor implements Executor, Serializable {
        private static final long serialVersionUID = 1L;
        // 类成员与业务逻辑
    }
    
  2. BuildStep中序列化并生成资源文件
    将Executor实例序列化为字节数组,通过GeneratedResourceBuildItem写入类路径资源:
    @BuildStep
    void serializeExecutor(BuildProducer<GeneratedResourceBuildItem> producer) throws IOException {
        Executor executor = parseTextFileToExecutor();
    
        // 序列化实例到字节数组
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
            oos.writeObject(executor);
        }
        byte[] serializedBytes = baos.toByteArray();
    
        // 生成资源文件:META-INF/executor/serialized-executor.ser
        producer.produce(GeneratedResourceBuildItem.builder()
                .setResourcePath("META-INF/executor/serialized-executor.ser")
                .setContent(serializedBytes)
                .build());
    }
    
  3. 运行时反序列化获取实例
    在运行时读取资源并反序列化:
    @ApplicationScoped
    public class ExecutorProducer {
        @Produces
        public Executor getExecutor() throws IOException, ClassNotFoundException {
            try (InputStream is = getClass().getResourceAsStream("/META-INF/executor/serialized-executor.ser");
                 ObjectInputStream ois = new ObjectInputStream(is)) {
                return (Executor) ois.readObject();
            }
        }
    }
    

同类扩展参考

  • Quarkus REST扩展:构建阶段生成路由处理类,运行时直接加载调用,无需序列化。
  • Quarkus Arc扩展:构建阶段生成依赖注入相关的字节码类,比如生产者代理类。
  • Hibernate ORM Quarkus扩展:构建阶段生成实体元数据相关的字节码,运行时直接使用。

注意事项

  • 字节码生成方式性能最优,且避免了序列化的版本兼容、非Serializable依赖等问题,优先推荐。
  • 原生序列化方式需确保所有涉及的类(包括成员变量类型)都实现Serializable,否则会抛出异常。
  • 构建阶段和运行时的类加载器不同,用GeneratedResourceBuildItem生成的资源会被正确打包到应用中,运行时可正常读取。

内容的提问来源于stack exchange,提问作者Claudio D'Angelo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 07:03:27