如何在 ByteBuddy 转换期间扩充方法?
How to augment methods during ByteBuddy transformation?
上下文
我正在使用 ByteBuddy 实现字节码转换,操作过程是一个多步骤过程。
因此,操作必须能够:
- 扩充原有的方法
- 完全创建新方法
- 扩充通过 2.
引入的方法
对于 1. 我使用了 @OnMethodExit
建议,通过以下方式应用:
Builder<?> builder = builder.visit(Advice.to(Helper.class)
.on(ElementMatchers.hasMethodNamed(name));
和 Helper
方法的扩充代码(有效地设置字段的值)。
创建新方法时,我按如下方式构建它们:
Builder<?> builder = builder.defineMethod(…)
.intercept(MethodDelegation.to(OtherHelper.class));
.…;
OtherHelper
通过以 @This Object object
作为参数的静态方法使用运行时实例。
问题
简而言之:如果 前 转换遵循后者,我没有看到应用。
实际执行顺序如下:
- 我的类型得到处理并通过
MethodDelegation.…
添加了一个方法。
- 在随后的步骤中,我发现了新引入的方法,并尝试使用
@OnMethodExit
建议通过 Advice.to(…)
增加实现生成。
- 生成的代码具有步骤 1 的行为,但缺少步骤 2 的行为。
我假设我无效地将实现的两个部分组合在一起。有任何想法吗?预感:ElementMatcher
是否按名称匹配扩充还没有看到使用 ….defineMethod(…)
引入的方法? name
来自我从 builder.toTypeDescription()
开始的一些方法检查,这实际上让我假设要创建的方法已经对构建器可见,否则它不会在该步骤中找到首先。
你能分享你的例子的重建吗?在一个简单的例子中,我观察到了预期的行为:
public class Bar {
public static void main(String[] args) throws Exception {
Class<?> type = new ByteBuddy().subclass(Object.class)
.visit(Advice.to(Bar.class).on(named("m")))
.defineMethod("m", void.class, Visibility.PUBLIC)
.intercept(MethodDelegation.to(Bar.class))
.make()
.load(Bar.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
type.getMethod("m").invoke(type.getConstructor().newInstance());
}
@BindingPriority(2)
public static void delegation() {
System.out.println("Delegation!");
}
@Advice.OnMethodEnter
public static void enter() {
System.out.println("Advice!");
}
}
此示例同时打印 Advice! 和 Delegation!.
上下文
我正在使用 ByteBuddy 实现字节码转换,操作过程是一个多步骤过程。 因此,操作必须能够:
- 扩充原有的方法
- 完全创建新方法
- 扩充通过 2. 引入的方法
对于 1. 我使用了 @OnMethodExit
建议,通过以下方式应用:
Builder<?> builder = builder.visit(Advice.to(Helper.class)
.on(ElementMatchers.hasMethodNamed(name));
和 Helper
方法的扩充代码(有效地设置字段的值)。
创建新方法时,我按如下方式构建它们:
Builder<?> builder = builder.defineMethod(…)
.intercept(MethodDelegation.to(OtherHelper.class));
.…;
OtherHelper
通过以 @This Object object
作为参数的静态方法使用运行时实例。
问题
简而言之:如果 前 转换遵循后者,我没有看到应用。 实际执行顺序如下:
- 我的类型得到处理并通过
MethodDelegation.…
添加了一个方法。 - 在随后的步骤中,我发现了新引入的方法,并尝试使用
@OnMethodExit
建议通过Advice.to(…)
增加实现生成。 - 生成的代码具有步骤 1 的行为,但缺少步骤 2 的行为。
我假设我无效地将实现的两个部分组合在一起。有任何想法吗?预感:ElementMatcher
是否按名称匹配扩充还没有看到使用 ….defineMethod(…)
引入的方法? name
来自我从 builder.toTypeDescription()
开始的一些方法检查,这实际上让我假设要创建的方法已经对构建器可见,否则它不会在该步骤中找到首先。
你能分享你的例子的重建吗?在一个简单的例子中,我观察到了预期的行为:
public class Bar {
public static void main(String[] args) throws Exception {
Class<?> type = new ByteBuddy().subclass(Object.class)
.visit(Advice.to(Bar.class).on(named("m")))
.defineMethod("m", void.class, Visibility.PUBLIC)
.intercept(MethodDelegation.to(Bar.class))
.make()
.load(Bar.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
type.getMethod("m").invoke(type.getConstructor().newInstance());
}
@BindingPriority(2)
public static void delegation() {
System.out.println("Delegation!");
}
@Advice.OnMethodEnter
public static void enter() {
System.out.println("Advice!");
}
}
此示例同时打印 Advice! 和 Delegation!.