ByteBuddy拦截方法中使用MethodCall调用可变长参数方法如何传入多个字段
错误根因
Arrays.asList()的可变参数是Java语法糖,实际字节码层面的方法签名是public static List asList(Object[]),仅接收1个数组类型参数。你直接调用withField("a", "b")会尝试向该方法传递2个int类型参数,自然出现参数不匹配异常,同时int基本类型需要装箱为Integer才能存入Object数组。
可行实现方案
方案1:使用Advice实现(更简洁易维护,推荐)
ByteBuddy的Advice机制可以直接写Java代码实现逻辑,不需要手动拼接方法调用参数,适配性更强:
首先定义Advice切面类:
public class GetFieldsAdvice { @Advice.OnMethodExit public static void intercept(@Advice.This TestClass instance, @Advice.Return(readOnly = false) List<?> result) { // 直接编写业务逻辑,自动处理装箱、可变参数 result = Arrays.asList(instance.a, instance.b); } }
修改ByteBuddy实现代码:
new ByteBuddy() .rebase(TypePool.Default.ofSystemLoader().describe("com.test.TestClass").resolve(), ClassFileLocator.ForClassLoader.ofSystemLoader()) .method(ElementMatchers.named("getFields")) .intercept(Advice.to(GetFieldsAdvice.class)) .make() .load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.INJECTION) .getLoaded();
方案2:继续使用MethodCall,适配可变参数规则
如果要保留MethodCall的实现方式,需要添加asVarArgs()配置自动打包参数为数组,同时手动处理基本类型装箱:
new ByteBuddy() .rebase(TypePool.Default.ofSystemLoader().describe("com.test.TestClass").resolve(), ClassFileLocator.ForClassLoader.ofSystemLoader()) .method(ElementMatchers.named("getFields")) .intercept(MethodCall.invoke(Arrays.class.getMethod("asList", Object[].class)) .withField("a").as(Integer.class) .withField("b").as(Integer.class) .asVarArgs()) // 自动将多个参数包装为Object数组传入可变参数方法 .make() .load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.INJECTION) .getLoaded();
内容的提问来源于stack exchange,提问作者Noname
相关产品推荐
相关产品推荐

