有没有办法定义一个方法,每次我调用 get 时都会调用它?
我有一个对象联系人,不想设置 updateLastUsed(); 为我的会员提供大约 30 个吸气剂。
您可以创建一个将属性名称作为输入的通用 getter,而不是访问属性的 getter。如果您的属性属于不同类型,则返回类型需要是 Object。
在这个通用 getter 中,您调用属性 getter 和 updateLastUsed() 方法。为了安全起见,将所有财产获取者设为私有。
您可以添加对每个方法的调用(无聊),或使用某种形式的 AOP(例如 AspectJ,下面的示例)来匹配类型的 getter 并调用 updateLastUsed() 方法。
编辑:有几个人指出 30 个 getter 是一种代码味道,调用另一种方法是一种副作用。第一个陈述是一个公平的指标,但不是一个规则。拥有这种类型可能有很多原因,如果没有更多信息,我会将其作为建议,以检查您是否可以将职责分为两种或多种类型。
关于副作用的另一点可能相关也可能不相关。有许多横切关注点适用于 getter 方法是有意义的。例如日志记录、身份验证和缓存。示例方法 updateLastUsed() 可能是缓存策略的一部分,因此在我看来,对这个问题的无条件批评是不值得的。
如何在 AspectJ 中实现切入点和通知的示例如下:
package test;
public aspect TestAspect {
/**
* Match all getters of test.Contact and bind the target.
*/
protected pointcut contactGetters(Contact contact) :
execution(* test.Contact.get*()) && target(contact);
/**
* Before execution of each getter, invoke the updateLastUsed() method
* of the bound target.
*/
before(Contact contact): contactGetters(contact) {
contact.updateLastUsed();
}
}
我会建议 AOP,但如果它是 J2ME,我们谈论的是你最好在你的 30 个访问器中手动插入“onGetCalled()”,然后在该方法中编码你需要的任何东西。您可能需要传入被调用的方法(或访问的属性)的名称,以备将来需要时使用。
这看起来像是面向方面编程 (AOP) 的工作。
为任何以get*
“新的”AspectJ 5 支持使用注释来定义方面切入点,因此您可以对 getter 进行注释以调用@Before
执行方法主体的切入点。
需要像 AOP 这样的东西来做到这一点。除了this之外,我不知道 J2ME 对它的支持程度如何。
除了 AOP,您还可以使用java.lang.reflect.Proxy
, 或字节码操作...
但不是在 J2ME 上
我建议调用 updateLastUsed() 30 次。
这是一个方法。它不漂亮,但你可能更喜欢它而不是重复:
public class GetterTest extends TestCase {
private static class Thing {
public int accessCount;
private String name;
private int age;
private <T> T get(T t) {
accessCount++;
return t;
}
public String getName() {
return get(name);
}
public int getAge() {
return get(age);
}
}
public void testGetIncrementsAccessCount() throws Exception {
Thing t = new Thing();
assertEquals(0, t.accessCount);
t.getName();
assertEquals(1, t.accessCount);
t.getAge();
assertEquals(2, t.accessCount);
}
}
显然,我的 get() 只是增加 accessCount,你会想要一些其他的行为,但想法就在那里。
使用正则表达式将方法调用附加到 getter 标头。
寻找:
\w+ get\w+\s*\(\)\s*\{(\s*)
用。。。来代替:
\0updateLastUsed();\1
这些表达式使用 Eclipse 3.5 (Galileo) 在“查找/替换”对话框中使用“全部替换”进行了测试。
请注意,您使用的编辑器必须支持多行匹配(或者您必须启用它)。对于 EmEditor 8.05,我必须将搜索字符串修改为:
\w+ get\w+\s*\(\)\s*\{\s*(\n\s*)
以便显式匹配新行。替换字符串保持原样。
你可以做一些花哨的事情,但老实说,这就是为什么将宏添加到编辑器中的原因,这样你就可以快速重复无聊的代码。
我只会让所有 getter 调用该方法,然后使用宏来创建调用(如果它需要因方法而异)。这一切只需要做一次,然后你就忘了它......
我会说代理对象以调用所需的方法。