Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用ByteBuddy向现有实例添加字段?_Java_Spring_Byte Buddy_Mongotemplate - Fatal编程技术网

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

Java 如何使用ByteBuddy向现有实例添加字段?,java,spring,byte-buddy,mongotemplate,Java,Spring,Byte Buddy,Mongotemplate,我需要将文档从Spring应用程序扔到MongoDB实例,在那里我可以利用MongoTemplate的数据包 但是Spring将这些实例id字段作为MongoDB文档id,从而在数据库中产生重复的id,从而防止重复的实例 这是一个项目,其中: 我需要将数据从数据库本身,而不是从应用程序中抛出到MongoDB实例,以便以后进行分析(因此我不在乎是否无法查询它们) 重复文件可能存在,并且是要求的一部分 文档是web服务请求的反序列化,我可以在类定义中添加一个\u id字段,但是将来从WSDL生成的

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

但是Spring将这些实例
id
字段作为MongoDB文档id,从而在数据库中产生重复的id,从而防止重复的实例

这是一个项目,其中:

  • 我需要将数据从数据库本身,而不是从应用程序中抛出到MongoDB实例,以便以后进行分析(因此我不在乎是否无法查询它们)
  • 重复文件可能存在,并且是要求的一部分
  • 文档是web服务请求的反序列化,我可以在类定义中添加一个
    \u id
    字段,但是将来从WSDL生成的源代码将丢弃该字段
  • 在这个初始阶段,文档是以这种方式进行测试的,在收集和分析了一些数据之后,它们不会被发送到数据库
从中可以看出,Spring必须有一个
id
字段,我需要以某种方式添加一个
\u id
字段

以下是我将文档插入集合的方式:

public void save(List<MyDocument> docs) {
    mongoTemplate.insert(MyDocument.class).inCollection("docscoll").all(docs);
}
但它在以下方面失败了:

Cannot inject already loaded type: class com.MyDocument

这是行不通的。大多数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>);
newagentbuilder.Default()
.type(命名为“.MyDocument”))
.transform((生成器、类型描述、类加载器、模块)->builder
.defineField(“_id”,int.class,Visibility.PUBLIC))
.installOn();
这样,如果在代理的
premain
方法中添加此代码,则在首次加载类之前添加该字段


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

这听起来像是一个可怕的黑客攻击,可以用一种更简单的方法来完成。我不确定我是否完全理解您需要做什么,但是:为什么不使用必需的字段定义您自己的类,然后通过复制字段将
MyDocument
的实例转换为该类,然后将新类的对象保存到MongoDB?没有必要进行字节码黑客攻击…@Jesper是的,确实如此。除了有很多字段和向代码中添加bug的风险很小之外,我喜欢将对象添加到存储中的想法。事实上,这是春天迫使我找到一个黑客,MongoDB会接受文档的原样并自动添加id。我明白了。是的,这看起来不是解决问题的好办法。
new AgentBuilder.Default()
  .type(named("<package>.MyDocument"))
  .transform((builder, typeDescription, classLoader, module) -> builder
    .defineField("_id", int.class, Visibility.PUBLIC))
  .installOn(<instrumentation>);