【问题标题】:Javassist instrumenting field accessesJavassist 检测字段访问
【发布时间】:2015-11-20 16:55:01
【问题描述】:

有谁知道是否有任何方法可以使用 Javassits 拦截被访问类上的字段访问?

public class Original{
    public int field;
}

public class User {
    Original o;
        ...
    public int query(){
        return o.field;
    }
    public void set(){
        o.field=3;
    }
}

我想要的是,每当另一个类从任何原始实例访问该字段时,它都会运行一些额外的代码(例如System.out.println("Reading field");

我知道扩展类 javassist.expr.ExprEditor 并实现方法void edit(FieldAccess fa),我可以替换我想要的任何其他代码的字段访问,但在访问类上。

这需要修改访问该字段的任何类。在我们的示例中,用户类 a 将所有读取访问替换为 System.out.println(...);XXX=o.field,并将所有写入访问替换为 System.out.println(...);o.field=XXX

我想做的是将常规类实例转换为代理,以便任何字段访问都会触发方法执行。可行吗?对可能的子类有影响吗?

提前致谢!

【问题讨论】:

    标签: java field javassist


    【解决方案1】:

    做到这一点的一种方法是将代理的所有字段设为私有,当然还需要提供相应的 setter/getter,之后,您将实现一个 MethodHandler,其中包含您要执行的方法(即调用),然后您需要实现一个 MethodFilter,您将在其中指定要拦截的方法(在您的情况下为 getter/setter)

    我认为您已经熟悉 javassist,因此我认为不需要代码示例,否则我可以编辑这篇文章以提供示例

    我希望你能明白 ;)

    【讨论】:

    • 我明白了。我知道如何通过处理程序调用添加 getter 和 setter,以及如何更改字段定义。到目前为止,不需要代码。我不清楚的是其他类(已经编译)将如何通过调用这些 getter/setter 而不是尝试读取私有属性来替换它们对字段的访问。
    • 很抱歉耽搁了,这些 getter 和 setter 将被代理,您的客户端代码不必更改,您将在 MethodHandler 中处理拦截
    • 没问题,这是我正在考虑的长期发展。现在只是评估可能性。我不确定我是否正确理解了您的意思。我真的很感激一个代码示例(简单的一个)。我编辑了这个问题以缓解它。在您的解决方案中,您将创建一个代理子类,还是只修改原始子类?
    • 由于您可以直接访问,因此您的客户端代码必须更改,我不知道您还能如何做到这一点,我的想法只是使用子类装饰访问器(getter/setter)代理,对不起,我帮不上什么忙
    • 这就是我所害怕的 :( 无论如何感谢您的帮助
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-11
    • 2015-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多