在编译/运行时替换Java类型

时间:2013-01-02 12:58:10

标签: java profiling

我有一个我要替换的类型列表,用于记录目的,但是没有更改我的代码(日志记录部分只是为了使用它)。我正在寻找一种简单的方法来为我的类字段创建某种代理,以便在运行时知道我的类字段何时被更改,或者当我没有类源代码时(例如LinkedList),调用类方法时。

作为一个例子,如果我有这个代码,这是一个属于我的类,我只需要警告MyClass字段状态的变化:

public class MyClass {

   private LinkedList<Integer> myList;

   private int myInteger;

   public void myMethod() 
   {
      myInteger = 15;
      myList = new LinkedList<Integer>();
   }

   public void myOtherMethod()
   {
      myList.add(1);
   }

   public LinkedList<Integer> getMyList() {
      return myList;
   }
}

我需要知道,在运行时(但代码修改可以在编译时完成),每当有人更改myInteger的值时,向myList添加一个元素并更改{{ 1}}引用myList。我认为解决方案不应该完全使用代码分析,因为列表引用可以通过参数传递到任何地方,例如LinkedList

在这种情况下,记录它只是用于字段,而它们是原始的或对象。对于我没有代码的类型(如LinkedList),如果在调用某个方法或读取或写入任何公共字段时收到通知,我会很高兴。

2 个答案:

答案 0 :(得分:3)

您可以使用AspectJ来挂钩这些事件...请参阅pointcuts了解何时可以挂钩的信息。

或者您使用CGLib或任何其他字节码库在加载时修改字节码并注入其他逻辑,例如在字段访问时递增访问计数器或类似的东西。

或者您扩展Lombok以编织所需的代码。 (我发现这比修改普通的java字节码更容易)。这将是编译时间

答案 1 :(得分:0)

我建议你只返回一个集合的接口(不是一个具体的类)并使它成为不可变的。

public class MyClass {
    private final List<Integer> myList = new ArrayList<>();
    private int myInteger;

    public void myMethod() {
        myInteger = 15;
    }

    public void myOtherMethod(int i) {
        myList.add(i);
    }

    public List<Integer> getMyList() {
        return Collections.unmodifiableList(myList);
    }
}

正如您所看到的,调用者无法修改列表,因此在发生这种情况时您无需收到通知。如果调用者想要修改列表,则必须调用您的一种方法,在这种情况下,您将了解这些更改。

  

我没有类源代码(例如LinkedList),

您可以访问它,您不应该修改它。 (如果你真的想要,也可以这样做)

相反,您可以对集合进行子类化,该集合将修改您更改的任何方法。但是,返回不可变集合是最佳实践。