微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在groovy @Canonical bean构造函数调用中添加缺少的属性?

我是groovy的新手,刚开始探索它的元编程功能.我坚持在bean构造函数调用添加缺少的属性.

在与FactoryBuilderSupport一起使用的类中,我想动态添加在构造函数调用期间尚未定义和提供的那些属性.这是精简版:

@Canonical
class MyClass {
    def startDate
    def additionalProperties = [:]

    def void propertyMissing(String name,value) {
        additionalProperties[name] = value
    }
}

但是,如果我构造具有未知属性的类,则不会添加proprty,但我会得到一个MissingPropertyException:

def thing = new MyClass(startDate: DateTime.Now(),duration: 1234)

属性持续时间不存在,我预计它将通过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()

生成的构造函数

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

由于公共MyClass(java.util.LinkedHashMap)生成,您不能使用tuple-constructor,并且您得到MissingPropertyException.

令人惊讶的是,如果您使用类型而不是使用def定义您的第一个对象(请注意我说第一个),@ Canon注释不会添加公共MyClass(java.util.LinkedHashMap),然后您的元组构造函数调用工作,请参阅以下代码

@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)

因此,由于没有公共MyClass(java.util.LinkedHashMap),因此限制不适用,并且您的元组构造函数调用有效.

另外我想说,既然这个解决方案有效,我无法争辩为什么……我一次又一次地阅读@Canonical文档,我没有看到描述这种行为的部分,所以我不知道为什么以这种方式工作,我也做了一些尝试,我有点困惑,只有当第一个元素是def时,公共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和公共MyClass(java.util.LinkedHashMap)没有生成

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

希望这可以帮助,

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐