当前位置: 首页 > 知识库问答 >
问题:

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

屈浩波
2023-03-14

我需要从Spring应用程序向MongoDB实例抛出文档,在那里我可以利用其数据包中的MongoTemplate。

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

    null

通过阅读这个问题,我发现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

共有1个答案

岳刚洁
2023-03-14

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

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

但是,由于VM的限制,这将不起作用,您还可以更改方法内容。

您可以附加一个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>);

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

 类似资料:
  • 我试了一些Apache Ignite的例子。我正在以以下格式提供我的Ignite节点的地址 memberStrings的值取自一个输入文件,我想将一个地址动态添加到ignite节点。为了简单起见,假设ignite已经在地址A和B中运行,这两个地址都存在于MemberStrings中。拓扑快照类似于 假设我在输入文件中添加一个新地址'C'。我有一个正在运行的线程,它检测这个更改并在MemberStr

  • 有没有办法使用springmongo将新字段添加到所有现有文档中。 寻找类似的东西 db.collection.update({"all_document"},

  • 问题内容: 我已经使用python创建了一个txt文件,其中包含几行文本,这些文本将由一个简单的程序读取。但是,我在重新打开文件以及在程序的后续部分中在文件中写入其他行时遇到了一些麻烦。(这些行将从稍后获得的用户输入中写入。) 这是假设“ file.txt”已被打开并被写入。但是,使用我当前拥有的代码第二次打开该文件时,我必须擦除之前编写的所有内容并重写新行。有没有办法防止这种情况发生(并可能减少

  • 作为一个具体的示例,假设我有一个工作簿和工作表,其中有一个从A1开始的2列2行(包括标题)的现有表。我可以打开底层的XL>Tables>Table1.xml并看到以下内容: 我可以看到我的两列、根标记的ref属性以及autoFilter块的ref属性。我想要做的是添加一个新行,这样表的面积将是A1:B3。

  • 问题内容: 我已经读到,可以在Python中添加一个方法到现有对象(即,不是在类定义中)。 我知道这样做并不总是好的。但我们怎么做呢? 问题答案: 在Python中,函数和绑定方法之间存在差异。 绑定方法已“绑定”(描述性)到一个实例,并且无论何时调用该方法,该实例都将作为第一个参数传递。 但是,作为类(而不是实例)的属性的可调用对象仍未绑定,因此你可以在需要时随时修改类定义: 先前定义的实例也会

  • 例如,假设有一个接口(StoredOnDatabase)带有一些有用的方法,可以从数据库中读取和写入bean。假设有一些类没有实现这个接口,而是用注释@bean进行了注释。当这个注释出现时,我想: 创建实现StoredonDatabase接口的bean代理; 为setter添加拦截器,当bean的属性被修改时,我可以使用这些拦截器来“跟踪”; 使用对所有这些bean都有效的泛型equals()和h