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

Quarkus是否支持类似AspectJ的加载时织入?如何无源码修改加拦截器

Quarkus中的加载时织入与无源码修改的拦截方案

Quarkus本身支持字节码增强,类似AspectJ的加载时织入(LTW),可以通过以下几种方式实现无源码修改的拦截需求:

1. 使用Quarkus的Bytecode Transformer扩展

Quarkus提供了io.quarkus.transformer扩展,允许你在类加载阶段修改字节码,无需修改原始源码:

  • 实现BytecodeTransformer接口,定义对目标类(比如C或接口I)的增强逻辑
  • 在Transformer中拦截myMethod的调用,插入指标生成代码
  • 注册Transformer到Quarkus的扩展机制中,测试时会自动生效

示例Transformer伪代码:

@Recorder
public class MetricsTransformerRecorder {
    public BytecodeTransformer transform() {
        return new BytecodeTransformer() {
            @Override
            public byte[] transform(ClassLoader classLoader, String className, byte[] originalBytes) {
                if ("com.example.C".equals(className)) {
                    // 使用ASM修改字节码,在myMethod前后插入指标逻辑
                    ClassReader cr = new ClassReader(originalBytes);
                    ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
                    ClassVisitor cv = new ClassVisitor(Opcodes.ASM9, cw) {
                        @Override
                        public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
                            MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
                            if ("myMethod".equals(name) && "()V".equals(descriptor)) {
                                // 插入前置指标代码
                                mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/example/MetricsCollector", "recordStart", "()V", false);
                                // 保留原方法逻辑
                                // 插入后置指标代码
                                mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/example/MetricsCollector", "recordEnd", "()V", false);
                            }
                            return mv;
                        }
                    };
                    cr.accept(cv, ClassReader.EXPAND_FRAMES);
                    return cw.toByteArray();
                }
                return originalBytes;
            }
        };
    }
}

2. 结合ByteBuddy实现动态增强

你可以直接在Quarkus测试中使用ByteBuddy,在测试启动时动态修改目标类:

  • 在测试类的@BeforeAll方法中,使用ByteBuddy重新定义C类,拦截myMethod
  • 这种方式无需编写Quarkus扩展,适合测试场景快速验证

示例测试代码:

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.matcher.ElementMatchers;

public class CTest {
    @BeforeAll
    static void setup() {
        new ByteBuddy()
            .redefine(C.class)
            .method(ElementMatchers.named("myMethod"))
            .intercept(MethodDelegation.to(MetricsInterceptor.class))
            .make()
            .load(C.class.getClassLoader());
    }

    public static class MetricsInterceptor {
        public static void intercept(@SuperCall Runnable superCall) {
            // 前置指标逻辑
            MetricsCollector.recordStart();
            try {
                superCall.run();
            } finally {
                // 后置指标逻辑
                MetricsCollector.recordEnd();
            }
        }
    }

    @Test
    void testMyMethod() {
        new C().myMethod();
        // 验证指标生成
    }
}

3. 使用Quarkus的ArC扩展与CDI代理(限容器管理实例)

如果目标类能被CDI容器管理,也可以通过CDI拦截器实现:

  • 编程式注册C为CDI bean(无需修改源码,可通过自定义扩展或beans.xml配置)
  • 编写CDI拦截器,通过类/方法匹配规则指定切点,无需在目标方法上加注解
  • 注意:这种方式要求实例通过CDI容器获取(比如@Inject),而非直接new C()创建

注意事项

  • 测试场景优先选ByteBuddy动态增强,实现简单快捷
  • 字节码操作需确保符合JVM规范,避免破坏类结构
  • Quarkus dev模式下,字节码增强的修改需重启服务才能生效

内容的提问来源于stack exchange,提问作者cnmuc

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 22:07:28