如果我有这样一个时髦的课:
class WebSession{
String firstName
String lastName
String email
}
我希望能够使用自动设置器来设置值。例如:
WebSessionuser = new WebSession()
webSession.firstName = 'John'
但是它调用的setter做了额外的事情,比如记录某些内容或者将对象保留为缓存。
如何在不必手动定义所有设置器的情况下执行此操作?到目前为止,我有类似的东西,但我不能让它工作:
webSession.properties.each{ key, value ->
if ( key != 'class' ) {
String methodName = "set${key.capitalize()}";
WebSession.metaClass[key]."${methodName}" = { -> delegate
System.out.println("Setting key: ${key}");
webSession[key] = delegate;
}
}
}
另外,我不知道是否循环遍历属性名称减去'class'是hacky并且有更好的方法来获取声明的字段。
答案 0 :(得分:2)
您可以通过实施void setProperty(String, Object)
和Object getProperty(String)
拦截所有的getter和setter。这是一个例子:
def a = new WebSessionDecorator(new WebSession())
a.firstName = 'John'
println a.firstName
class WebSession {
String firstName
String lastName
String email
}
class WebSessionDecorator {
private WebSession delegate
WebSessionDecorator(WebSession webSession) {
this.delegate = webSession
}
void setProperty(String name, Object value) {
println "LOG: Setting $name to $value"
delegate.setProperty(name, value)
}
def getProperty(String name) {
println "LOG: Returning $name"
delegate.getProperty(name)
}
}
输出如下:
LOG: Setting firstName to John
LOG: Returning firstName
John
WebSessionDecorator
拦截所有属性访问权限,为您提供进行任何操作的机会。然后,它将属性访问委托给实际的WebSession
。
我选择使用装饰器以避免重复调用getProperty()
和setProperty()
,并且仅在适用时才可以使用装饰器。例如,您可能不想在单元测试中使用它。