我是 groovy 的新手,刚刚开始探索它的元编程功能。我遇到了在 bean 构造函数调用中添加缺失属性的问题。
在与 FactoryBuilderSupport 一起使用的类中,我想动态添加那些在构造函数调用期间尚未定义和提供的属性。这是精简版:
@Canonical
class MyClass {
def startDate
def additionalProperties = [:]
def void propertyMissing(String name, value) {
additionalProperties[name] = value
}
}
但是,如果我构造具有未知属性的类,则不会添加属性,但会得到
MissingPropertyException
反而:def thing = new MyClass(startDate: DateTime.now(), duration: 1234)
属性持续时间不存在,我希望通过
propertyMissing
处理它.据我了解 groovy,调用元组构造函数会导致无参数构造函数调用,然后调用 groovy 生成的 setter。那么为什么我会收到 MissingPropertyException
?由于我是 groovy 的新手,我可能缺少一些基本的 AST 或 MOP 规则。我非常感谢您的帮助。
最佳答案
如果您使用 @Canonical
然后用 def
定义第一个类对象就像你在做 startDate
注释生成以下构造函数:
@Canonical
class MyClass {
def startDate
def additionalProperties = [:]
def void propertyMissing(String name, value) {
additionalProperties[name] = value
}
}
// use reflection to see the constructors
MyClass.class.getConstructors()
生成的构造函数:
public MyClass()
public MyClass(java.lang.Object)
public MyClass(java.util.LinkedHashMap)
public MyClass(java.lang.Object,java.lang.Object)
在
@Canonical
documentation您可以看到以下限制:Groovy's normal map-style naming conventions will not be available if the first property has type LinkedHashMap or if there is a single Map, AbstractMap or HashMap property
由于
public MyClass(java.util.LinkedHashMap)
生成您不能使用 tuple-constructor
然后你会得到 MissingPropertyException
.令人惊讶的是,如果您定义了
first
对象(注意我说的是 first
)和 type
而不是使用 def
, @Canonical
注释不添加 public MyClass(java.util.LinkedHashMap)
然后是您的 tuple-constructor
调用有效,见以下代码:@Canonical
class MyClass {
java.util.Date startDate
def additionalProperties = [:]
def void propertyMissing(String name, value) {
additionalProperties[name] = value
}
}
// get the constructors
MyClass.class.getConstructors()
// now your code works
def thing = new MyClass(startDate: new java.util.Date(), duration: 1234)
现在创建的构造函数是:
public MyClass()
public MyClass(java.util.Date)
public MyClass(java.util.Date,java.lang.Object)
所以因为没有
public MyClass(java.util.LinkedHashMap)
限制不适用,您 tuple-constructor
通话作品。另外我想说,既然这个解决方案有效,我无法争论为什么...我读了
@Canonical
一次又一次的文档,我没有看到描述这种行为的部分,所以我不知道为什么会这样,我也做了一些尝试,但我有点困惑,只有当 first
元素是 def
public MyClass(java.util.LinkedHashMap)
被创建,即:@Canonical
class MyClass {
def a
int c
}
// get the constructors
MyClass.class.getConstructors()
第一个对象定义为
def
...public MyClass()
public MyClass(java.lang.Object)
public MyClass(java.util.LinkedHashMap) // first def...
public MyClass(java.lang.Object,int)
现在,如果我更改顺序:
@Canonical
class MyClass {
int c
def a
}
// get the constructors
MyClass.class.getConstructors()
现在第一个不是
def
和 public MyClass(java.util.LinkedHashMap)
没有生成:public MyClass()
public MyClass(int)
public MyClass(int,java.lang.Object)
希望这可以帮助,
关于groovy - 在 groovy @Canonical bean 构造函数调用中添加缺少的属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26094166/