【问题标题】:Modify library class at runtime - java/maven在运行时修改库类 - java/maven
【发布时间】:2017-10-29 11:38:12
【问题描述】:

我正在开发一个 Maven 插件,我需要修改一个外部 jar 类(在 maven 执行期间使用),以添加:

  • 此类的新字段
  • 领域的吸气剂
  • 现有 setter 填充字段的一些行为

库代码应该使用我的“新”类,并且我希望能够使用 getter 来检索一些附加信息。

这个类的实例是在库代码中创建的(我没有在我的代码中创建它们,我只需要访问它们)。 类是非最终的公共类。

您知道这是否可行,哪种方法最好? ByteBuddy可以做到吗?

编辑:我无法包装该类,因为它没有在我自己的代码中实例化,让我详细说明一下。

有一个名为“Parser”的库类实例化和填充一些“Element”实例。我的代码如下:

List<library.Element> elements = new library.Parser(file).parse();

Parser.parse() 方法在每个元素上调用“Element.setProperties(List properties)”。 我希望能够丰富 setProperties 方法来存储原始属性列表(否则会丢失)

谢谢 朱利奥

【问题讨论】:

  • 类的实例在哪里创建?在库之外并用作输入或?课程结束了吗?
  • 根据您的问题编辑了问题。
  • 为什么要修改一个外部jar的类?为什么不编写一个简单的包装类并相应地对其进行更改并将jar与包装类一起使用,而不是编写一个完整的maven插件?
  • 也许 fork 依赖,根据需要重写类并在自己的 jar 中提供阴影版本?
  • 我已经进一步澄清了这个问题。我宁愿不分叉依赖,因为它只是一个类的一个小改动

标签: java maven byte-buddy


【解决方案1】:

最后我设法通过 byte-buddy 获得了想要的结果(我不知道这是否是最好的解决方案,但它有效):

  1. 仪器库类 (library.Element) 使用“rebase”策略将方法“setProperties”调用委托给拦截器。

注意:这必须在 library.Element.class 尚未加载时作为 maven 插件执行的第一条指令完成(我不想使用 JVM 代理)

  1. 将上面的拦截器定义为一个类,将原始'properties'值存储在全局映射中(key = 对象的身份哈希码,value = properties),然后调用库的原始'setProperties'方法.元素

  2. 更改我的代码以从地图中获取属性,而不是 library.Element getter(我已经有了此类的包装器)。

如果有人感兴趣,我可以展示一些代码。

【讨论】:

    【解决方案2】:

    您的建议听起来有点骇人听闻,一般来说,如果不从 JAR 生成源、修改它们,然后重新打包,您甚至无法实现。如果我遇到这个问题,我会考虑使用装饰器模式。您可以创建一个包装器来公开 JAR 的所有方法,但它会添加一个额外的字段以及一个 getter 和 setter。

    import com.giulio.old.jar.everything.*;
    
    public class WrapperOfJar {
        private String newField;
    
        public String getNewField() { // ... }
        public void setNewField() { // ... }
    
        // all getters and setters from current JAR
    }
    

    现在您的用户将看到相同的界面,以及针对您的领域的一种新方法。此答案假定有问题的类不是final

    【讨论】:

      猜你喜欢
      • 2017-09-03
      • 2010-12-08
      • 2011-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多