可以使用byte-buddy作为非反射方式来收集[field] / [method return]值作为集合或映射吗?

问题描述 投票:2回答:1

我试图找到有用的答案,但没有运气。我想知道是否可以使用byte-buddy进行跟踪:假设我们有一个包含值数的POJO。对于某些特定类型的处理,我只对某些内容感兴趣。我可以用注释标记它们,比如@ConditionalData我可以放在getter或字段上。然后我可以创建和接口,让我们说NVPProvider将返回地图字段名称 - 值。使用反射执行此操作是可能的,但它不太高效。我希望我可以使用byte buddy通过接口和实现方法扩展类,但我并没有真正找到如何构建实现它的实现。

我已经完成了以下的实现:

net.bytebuddy.implementation.Implementation

并尝试在网页周围搜索一些示例,但我还没有认识到正确的方法。

public interface NVPProvider {
    Map<String, Object> getDataAsNVP();
}

public <O> Builder<O> instrumentType(Builder<O> builder) {
    builder.implement(NVPProvider.class).method(net.bytebuddy.matcher.ElementMatchers.named("getDataAsNVP")).intercept( ??? );        
    return builder.implement(NVPProvider.class);
}

我想知道是否有一种方法可以迭代字段和getter并通过反射获取注释匹配Accessible对象,但是基于此我将能够组成接口方法实现迭代匹配的字段并贡献结果映射,虚构的生成代码看起来像:

Map<String, Object> result = new HashMap<>();
Object obj0 = getValue001();
result.put("getValue001", obj0);

Object ob10 = accesibleField1;
result.put("ob10 ", ob10 );

后来我可以添加注释属性以获得更好看的键。

我见过一些例子

MethodDelegation.to(interceptor)

然而,我现在看到如何在没有反思的情况下做到这一点。

我知道如何使用Javassist,你可以在其中编写你稍后编译的代码片段,但我不知道如何使用byte-buddy。我已经使用byte-budy通过在配置文件中动态定义的简单getter来扩展POJO,它看起来不错。只有一个字节操作工具会更干净。感谢您的任何建议。

java byte-buddy
1个回答
0
投票

这在Byte Buddy中是可能的,但您必须通过实现自己的Implementation或其底层ByteCodeAppender来制造自定义方法体。您可以直接使用ASM,因为这样的访问者公开他们的MethodVisitor但更容易一些,您也可以使用net.bytebuddy.implementation.bytecode包中提供的更高级别的结构。对于描述它的方法,首先要实例化哈希映射:

List<StackManipulation> m = new ArrayList<>();

// new HashMap<>();
m.add(TypeCreation.of(HashMap.class));
m.add(Duplication.SINGLE);
m.add(MethodInvocation.invoke(new MethodDescription.ForLoadedConstructor(HashMap.class.getConstructor());

随后,ByteCodeAppender提供了检测类型的描述,您可以从中导航到所有字段和方法,例如:

FieldDescription field = ...

// map.put(fieldName, fieldValue);
m.add(Duplication.SINGLE);
m.add(new TextConstant(field.getName());
m.add(MethodVariableAccess.loadThis());
m.add(FieldAccess.forField(field).read());
m.add(MethodInvocation.invoke(Map.class.getMethod("put", Object.class, Object.class)));
m.add(Removal.SINGLE);

上面的代码首先复制堆栈上的哈希映射以保留它以供进一步访问,然后将字段名称添加到堆栈,加载字段值,然后调用Map::put方法。最后,它会丢弃put方法的返回值。

最后,您需要通过添加MethodReturn.REFERENCE来返回地图。

您可以查看Byte Buddy中的其他Implementations以了解其工作原理,ASM提供了一个很好的字节代码基础教程,以解释字节代码模式需要遵循的堆栈隐喻。

© www.soinside.com 2019 - 2024. All rights reserved.