java - 如何使用 ByteBuddy 向现有实例添加字段?

标签 java spring byte-buddy mongotemplate

我需要从 Spring 应用程序将文档扔到 MongoDB 实例,我可以在其中利用其数据包中的 MongoTemplate。

但是Spring将这些实例id字段作为MongoDB文档id,导致数据库中出现重复的id,从而防止重复实例。

这是一个项目,其中:

  • 我需要将数据扔到 MongoDB 实例,以便以后从数据库本身而不是应用程序进行分析(所以我不在乎是否无法查询它们);
  • 重复文件可能存在,并且是要求的一部分;
  • 文档是 Web 服务请求的反序列化,我可以将 _id 字段添加到类定义中,但 future 从 WSDL 生成的源代码将丢弃该字段;
  • 在初始阶段,出于测试目的,以这种方式处理文档,在收集和分析一些数据后,它们不会发送到数据库

阅读自this question我发现 id 字段对于 Spring 是必需的,我需要以某种方式添加一个 _id 字段。

这就是我将文档插入集合的方式:

public void save(List<MyDocument> docs) {
    mongoTemplate.insert(MyDocument.class).inCollection("docscoll").all(docs);
}

我对 ByteBuddy 完全陌生(我认为这可能是适合这项工作的库,但请随意建议另一个库),通过在此处搜索,我将以下代码放在一起:

new ByteBuddy()
  .redefine(MyDocument.class)
  .defineField("_id", int.class, Visibility.PUBLIC)
  .make()
  .load(MyDocument.class.getClassLoader(), ClassLoadingStrategy.Default.INJECTION);

但它失败了:

Cannot inject already loaded type: class com.MyDocument

最佳答案

这行不通。大多数 JVM 不允许向已加载的类添加字段。因此,尽管 Byte Buddy 可以调整字节码,但即使在类加载后正确完成,这也不起作用。正确的方法还需要一个 Java 代理,可以使用 Byte Buddy Agent 项目附加该代理,例如:

new ByteBuddy()
  .redefine(MyDocument.class)
  .defineField("_id", int.class, Visibility.PUBLIC)
  .make()
  .load(MyDocument.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());

但是,由于虚拟机限制,这不起作用,您也可以更改方法内容。

您可以附加一个 Java 代理,以便在应用程序启动之前添加尚未加载类的字段。这可以使用 Java 代理来完成,并且 Byte Buddy 可以轻松实现这样的代理:

new AgentBuilder.Default()
  .type(named("<package>.MyDocument"))
  .transform((builder, typeDescription, classLoader, module) -> builder
    .defineField("_id", int.class, Visibility.PUBLIC))
  .installOn(<instrumentation>);

这样,如果您在代理的 premain 方法中添加此代码,则该字段会在首次加载类之前添加。

但是我确实想知道这是否是解决您问题的正确方法。我通常宁愿使用弱映射而不是字节码检测。

关于java - 如何使用 ByteBuddy 向现有实例添加字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58485870/

相关文章:

java - ByteBuddy - 读取 java 代理中的类注释

java - 有没有办法从 ByteBuddy 的拦截器中通过 MethodDescription 调用方法?

java - pull 后,Eclipse 中的 Git 项目从工作区消失

java - 来自抽象 T 类型类的依赖注入(inject)

java - 将 Bufferedimage 转换为 MultipartFile

java - Spring MVC 与 Spring Webflow

java - Byte Buddy 的方法委托(delegate)

java - 安卓。如何使对话框按钮出现在对话框之外

java - 抽屉导航选择的项目不显示第二组项目的背景颜色

java - 单击按钮时 setText 不会更改或更新