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

标签 groovy mop

我是 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()

现在第一个不是defpublic 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/

相关文章:

grails - Groovy-具有多个引用的闭合

common-lisp - 如何访问元对象/槽定义槽?为什么 slot-value 可以访问对象的槽,但不能访问元对象的槽?

lisp:如何在范围内创建临时方法特化

syntax - Groovy 范围,步长为 0.5

sql - Grails更新生产数据库

jquery - 在 Grails 应用程序中放置何处以及如何访问 jQuery 插件?

grails - 通过键访问存储在映射中的配置变量

common-lisp - 获取类优先列表时未绑定(bind)插槽?

groovy - Groovy 中 propertyMissing 方法的静态版本是什么?