Quarkus扩展构建阶段解析Executor实例后序列化保存方案咨询
解决方案:Quarkus构建阶段保存Executor实例的两种原生方式
方案一:字节码生成(推荐,Quarkus原生风格)
这是Quarkus扩展最常用的实现思路,完全规避序列化环节,直接在构建阶段生成能返回预构建Executor实例的Java类,运行时直接调用即可。Quarkus本身依赖ByteBuddy,无需额外引入第三方依赖。
实现步骤
- 在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()); } - 运行时获取Executor实例
直接通过静态方法调用,或者用Arc的生产者注入:@ApplicationScoped public class ExecutorProducer { @Produces public Executor getExecutor() { return com.yourpackage.GeneratedExecutorProvider.getExecutor(); } }
方案二:Java原生序列化 + GeneratedResourceBuildItem
如果你的Executor及其所有子类都能实现java.io.Serializable,可以采用这种方式,同样无需额外依赖。
实现步骤
- 确保所有Executor类实现Serializable
给每个Executor子类添加Serializable接口,并显式声明serialVersionUID:public class StringExecutor implements Executor, Serializable { private static final long serialVersionUID = 1L; // 类成员与业务逻辑 } - 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()); } - 运行时反序列化获取实例
在运行时读取资源并反序列化:@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
相关产品推荐
相关产品推荐

