【问题标题】:Accessing fields from a proxied object从代理对象访问字段
【发布时间】:2012-03-30 11:35:52
【问题描述】:

我在为 Android 开发 ORM 框架时遇到了一个有趣的问题。我正在使用一个名为 dexmaker 的库进行字节码操作,这使我能够为持久对象创建代理以实现延迟加载。

代理实例具有关联的InvocationHandler,因此当在代理上调用方法时,invoke 方法会在InvocationHandler 上调用,然后假设代理对象已被延迟加载,则会调用代理对象的相应方法。没什么太令人惊讶的——它就像 Java 的 Proxy 类,但允许我代理实际的类而不是接口(参见 dexmaker 的 ProxyBuilder)。

成为问题的部分是我还使用反射从持久对象中检索字段值,并且——现在我已经引入了延迟加载——代理。这是我目前正在做的事情:

for (Field f : getPersistentFields(model.getClass()) {
    ...
    Object val = f.get(model); // model is either a persistent object or a proxy for one
    mapField(f, val, map);
}

这当然适用于常规模型实例,但对于代理实例,f.get(model) 不会检索代理对象的字段值。相反,它返回在类的构造函数中分配的默认值。对代理字段的访问明显没有被拦截。

我的问题是:有什么方法可以拦截通过反射对代理的成员变量进行的访问?如果不是,我如何以“类似反射”的方式检索代理字段的值?

一种可能的解决方法我正在考虑检索然后使用反射调用该字段的 getter 方法,但我想知道是否有更直接的解决方案。这种解决方法,如果它真的工作,将要求对象有一个用于所有持久字段的 getter 方法——从 OO 设计的角度来看,这个要求通常应该遵循,但也需要做更多的工作到框架的用户身上。

我愿意接受任何想法。

【问题讨论】:

  • 字段还在修改吗?怎么样?
  • 代理字段没有被修改。
  • 您能详细说明一下您的设计吗?代理类是代表模型还是与模型对象有连接?
  • @Stefan:代理代表模型。它们不是加载对象的相关模型,而是初始化为代理。然后,当访问代理时,例如通过调用其方法之一,InvocationHandler 将拦截方法调用,加载实际模型对象,并在新加载的对象上调用方法。
  • 客户端总是访问调用方法的模型?这个问题仅限于框架内部?

标签: java android reflection proxy dalvik


【解决方案1】:

一个好的解决方案是使用 setter/getter 而不是使用 Field 类来访问字段。 (我相信这不仅仅是一种解决方法)

另一方面,如果您想使用直接字段访问方法。据我所知,没有简单的方法来拦截字段访问。请查看this question 的答案。尽管问题与拦截字段修改而不是阅读有关 领域,它可能会提供一些见解和方向。

【讨论】:

  • 谢谢,维齐尔。我继续实施第一种方法,使用 getter 方法访问字段。这似乎是最直接的方法,而且效果很好。
猜你喜欢
  • 1970-01-01
  • 2015-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多