我是groovy的新手,刚开始探索它的元编程功能.我坚持在bean构造函数调用中添加缺少的属性.
在与FactoryBuilderSupport一起使用的类中,我想动态添加在构造函数调用期间尚未定义和提供的那些属性.这是精简版:
@Canonical
class MyClass {
def startDate
def additionalProperties = [:]
def void propertyMissing(String name, value) {
additionalProperties[name] = value
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我构造具有未知属性的类,则不添加proprty但是我得到了一个MissingPropertyException:
def thing = new MyClass(startDate: DateTime.now(), duration: 1234)
Run Code Online (Sandbox Code Playgroud)
属性持续时间不存在,我预计它将通过处理propertyMissing.据我所知groovy,调用tuple-constructor会导致无参数构造函数调用,然后调用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()
Run Code Online (Sandbox Code Playgroud)
生成的构造函数:
public MyClass()
public MyClass(java.lang.Object)
public MyClass(java.util.LinkedHashMap)
public MyClass(java.lang.Object,java.lang.Object)
Run Code Online (Sandbox Code Playgroud)
在@Canonical 文档中您可以看到以下限制:
如果第一个属性的类型为 LinkedHashMap 或者只有一个 Map、AbstractMap 或 HashMap 属性,Groovy 的普通映射样式命名约定将不可用
由于public MyClass(java.util.LinkedHashMap)是生成的,所以您无法使用tuple-constructor,并且您得到了MissingPropertyException。
令人惊讶的是,如果您使用a而不是 using定义first对象(请注意,我说的是) ,注释不会添加 the ,然后您的调用就可以工作,请参阅以下代码:firsttypedef@Canonicalpublic 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)
Run Code Online (Sandbox Code Playgroud)
现在创建的构造函数是:
public MyClass()
public MyClass(java.util.Date)
public MyClass(java.util.Date,java.lang.Object)
Run Code Online (Sandbox Code Playgroud)
因此,由于不存在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()
Run Code Online (Sandbox Code Playgroud)
第一个对象定义为def...
public MyClass()
public MyClass(java.lang.Object)
public MyClass(java.util.LinkedHashMap) // first def...
public MyClass(java.lang.Object,int)
Run Code Online (Sandbox Code Playgroud)
现在如果我改变顺序:
@Canonical
class MyClass {
int c
def a
}
// get the constructors
MyClass.class.getConstructors()
Run Code Online (Sandbox Code Playgroud)
现在第一个不是def也public MyClass(java.util.LinkedHashMap)没有生成:
public MyClass()
public MyClass(int)
public MyClass(int,java.lang.Object)
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助,
| 归档时间: |
|
| 查看次数: |
703 次 |
| 最近记录: |