【发布时间】: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