5

我是 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 生成的设置器。那为什么我会得到一个MissingPropertyException

由于我是 groovy 的新手,我可能缺少一些基本的 AST 或 MOP 规则。我非常感谢您的帮助。

4

1 回答 1

1

如果您使用@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 文档中,您可以看到以下限制:

如果第一个属性的类型为 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)

现在创建的构造函数是:

public MyClass()
public MyClass(java.util.Date)
public MyClass(java.util.Date,java.lang.Object)

因此,由于没有public MyClass(java.util.LinkedHashMap)限制不适用,您tuple-constructor称之为作品。

另外我想说的是,由于这个解决方案有效,我无法争辩为什么......我@Canonical一遍又一遍地阅读文档,我没有看到描述这种行为的部分,所以我不知道为什么会这样方式,我也做了一些尝试,但我有点困惑,只有当first元素defpublic 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()

现在 first is notdefpublic MyClass(java.util.LinkedHashMap)没有生成:

public MyClass() 
public MyClass(int)
public MyClass(int,java.lang.Object)

希望这可以帮助,

于 2014-09-29T08:09:11.193 回答