Groovy 中如何获取类的属性信息?
可以用 MyClass.metaClass.properties 来获取一个 MetaProperty 对象,它有很多具体的实现类,例如 MetaBeanProperty 类。
如果 metaProperty 的类型是 MetaBeanProperty,那么可以用 MetaBeanProperty.field.field 得到 java 的 Field 对象。
如果是 trait 的属性,那么 MetaBeanProperty.field 是 null。
如何取到 trait 的属性呢?
首先 Trait 会被编译为 Java 中的一个 interface,所以在这个 java interface 中并没有对应的 fields,而只有 getter 和 setter。
可以用下面的方法取到 Java 的 Method:
metaProperty.getter.cachedClass.methods[0].cachedMethod
// 取到 annotations
metaProperty.getter.cachedClass.methods[0].cachedMethod.annotations
Groovy trait 的属性
如果一个类实现了某个trait 例如:
trait MyTrait {
String name
int count
}
class MyClass implements MyTrait {
String classProp
}
new MyClass(name: "yang", count: 10, classProp: "ok")
用 GroovyConsle 的‘script>inspect last’ 菜单项,可以看到创建的 object 的结构,如下:
对于 public fields 和 property 可以看到有一些 $ 符号开头的名称,这些是 static 的 trait 成员变量,而 name 等正常的 property 是 groovy 对象的属性。
参考:https://issues.apache.org/jira/browse/GROOVY-7950
Grails 中 command 的属性
在 Grails 中,一个 Command 对象是实现了 Validateable trait 的类。某些情况下我们不能用 command.properties 来获取属性的名称,因为某些情况下我们无法得到 instance object 而只能从 Class 中获取属性名信息。
可以使用下面的方法读取类的 properties 信息:
aClass.metaClass.properties.each { MetaProperty metaProperty ->
if (!(metaProperty.modifiers & Modifier.PUBLIC)) {
return
}
String fieldName = metaProperty.name
Class fieldType = metaProperty.type
Field field = null
if (metaProperty instanceof MetaBeanProperty) {
field = metaProperty.field?.field
}
}
这个方法有一个缺点,即对于 trait 而言,是取不到 field 对象的,因为 trait 的 property 并不会在实现类中有一个“实际”的 field 对象。
如何能给 trait 的property 添加annotation还需要研究。