繁体   English   中英

使用 ByteBuddy 向方法添加行为

[英]add behavior to method with ByteBuddy

给定Sample.someMethod(...)someMethod InvocationHandler decoration ,我想创建一个动态子类,用

someMethod(...) {
  decoration.invoke(...);
  super.someMethod(...);
}

我的代码如下所示:

    Class<? extends Sample> dynamicSubclass = new ByteBuddy()
        .subclass(Sample.class)
        .method(ElementMatchers.named("someMethod"))
            .intercept(new Implementation.Compound(
                InvocationHandlerAdapter.of(decoration),
                SuperMethodCall.INSTANCE))
        .make()
        .load(Sample.class.getClassLoader())  // line 42
        .getLoaded();

...并导致以下异常:

java.lang.VerifyError: Expecting a stack map frame
Exception Details:
  Location:
    pl/morgwai/sample/pojo/ByteBuddySample$Sample$ByteBuddy$PXUw8Sz7.someMethod(I)Ljava/lang/String; @27: aload_0
  Reason:
    Error exists in the bytecode
  Bytecode:
    0000000: b200 0a2a b200 0e04 bd00 1059 031b b800
    0000010: 1653 b900 1c04 00c0 001e b02a 1bb7 0020
    0000020: b0                                     

    at java.base/java.lang.Class.getDeclaredFields0(Native Method)
    at java.base/java.lang.Class.privateGetDeclaredFields(Class.java:3061)
    at java.base/java.lang.Class.getDeclaredField(Class.java:2409)
    at net.bytebuddy.implementation.LoadedTypeInitializer$ForStaticField.onLoad(LoadedTypeInitializer.java:122)
    at net.bytebuddy.implementation.LoadedTypeInitializer$Compound.onLoad(LoadedTypeInitializer.java:192)
    at net.bytebuddy.dynamic.TypeResolutionStrategy$Passive.initialize(TypeResolutionStrategy.java:102)
    at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:6292)
    at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:6281)
    at pl.morgwai.sample.pojo.ByteBuddySample.main(ByteBuddySample.java:42)

我做错了什么以及如何解决?
(我使用的是 byte-buddy 1.10.22 和 openjdk-11)

谢谢!

更新:

我能够实现

someMethod(...) {
  decoration.invoke(...);
}

someMethod(...) {
  super.someMethod(...);
}

通过分别执行.intercept(InvocationHandlerAdapter.of(decoration)).intercept(SuperMethodCall.INSTANCE) ,看来,我没有正确使用Implementation.Compound ...

更新2:

我也能达到

someMethod(...) {
  super.someMethod(...);
  decoration.invoke(...);
}

经过

.intercept(SuperMethodCall.INSTANCE.andThen(InvocationHandlerAdapter.of(decoration)))

但我不能反过来实现我需要的顺序,因为InvocationHandlerAdapter没有实现Implementation.Composable ...

正如Rafael Winterhalter 所解释的那样,这是一个无意的遗漏,在下一个版本中InvocationHandlerAdapter实现Composable提交已经推送),然后最简单的方法是

.intercept(InvocationHandlerAdapter.of(decoration).andThen(SuperMethodCall.INSTANCE))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM