首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ByteBuddy:在构造类的过程中在intercept中使用新定义的字段

ByteBuddy:在构造类的过程中在intercept中使用新定义的字段
EN

Stack Overflow用户
提问于 2017-01-11 16:56:51
回答 1查看 1.2K关注 0票数 1

我正在看别人写的一些ByteBuddy代码。他使用ByteBuddy生成运行时子类,这些子类被用作代理,将他的运行时的一些管理代码实现为特定的对象。

代码语言:javascript
运行
复制
Class<? extends T> newSubClass = new ByteBuddy(ClassFileVersion.ofThisVm())
                .subclass(classType)
                .defineField("_core", Object.class, Visibility.PUBLIC) //<---
                .method(ElementMatchers.isDeclaredBy(classType))
                .intercept(InvocationHandlerAdapter.of((proxy, method, m_args) -> {
                    //TODO: Need to replace core with _core as core is a function argument and will make it bound
                    return proxyHandler(core, method, m_args); //<--
                }))
                .make()
                .load(roleType.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
                .getLoaded();


T proxy = ReflectionHelper.newInstance(newSubClass, args);
newSubClass.getField("_core").set(proxy, core);

为了不将core对象直接绑定到lambda,我想使用新定义的字段_core,这样我就可以重用生成的类(而不是每次调用函数都重新生成它)。有没有办法做到这一点?

提前谢谢。

EN

回答 1

Stack Overflow用户

发布于 2017-01-12 16:47:10

您可以像定义方法一样定义自定义构造函数。定义构造函数的一个要点是,您需要另一个构造函数调用作为其第一条指令。您可以使用可以与FieldAccessor::ofField组合的MethodCall::invoke调用构造函数。

这样,您就可以像下面这样定义您的类:

代码语言:javascript
运行
复制
new ByteBuddy(ClassFileVersion.ofThisVm())
  .subclass(classType, ConstructorStrategy.Default.NO_CONSTRUCTORS)
  .defineConstructor(Visibility.PUBLIC)
    .withParameter(InvocationHandler.class)
    .intercept(MethodCall.invoke(classType.getDeclaredConstructor())
    .andThen(FieldAccessor.ofField("_core").setsArgumentAt(0)))
  .defineField("_core", InvocationHandler.class, Visibility.PUBLIC)
  .method(ElementMatchers.isDeclaredBy(classType))
    .intercept(InvocationHandlerAdapter.toField("_core"))
  .make();

这样,您可以为每个实例设置一个自定义InvocationHandler。如果您只想将状态存储在_core字段中并从拦截器访问此字段,请查看MethodDelegation

代码语言:javascript
运行
复制
new ByteBuddy(ClassFileVersion.ofThisVm())
  .subclass(classType, ConstructorStrategy.Default.NO_CONSTRUCTORS)
  .defineConstructor(Visibility.PUBLIC)
    .withParameter(Object.class)
    .intercept(MethodCall.invoke(classType.getDeclaredConstructor())
    .andThen(FieldAccessor.ofField("_core").setsArgumentAt(0)))
  .defineField("_core", Object.class, Visibility.PUBLIC)
  .method(ElementMatchers.isDeclaredBy(classType))
    .intercept(MethodDelegation.to(MyHandler.class))
  .make();

public class MyHandler {
  @RuntimeType
  public static Object intercept(@FieldValue("_core") Object value) { ... }
}

您可能需要的其他批注是@This@AllArguments@Origin@SuperCall。你需要的越少,你的代理的效率就越高。特别是@AllArguments,由于它的分配要求,它是昂贵的。

请注意,在这种情况下,您的字段仅在超级构造函数调用之后设置。此外,您还假设在超类型中有一个默认构造函数。或者,您可以实现自定义ConstructorStrategy

至于缓存,可以看看Byte Buddy的TypeCache

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41586467

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档