文章目录
一、GroovyObject 接口简介
二、MetaClass 简介
三、使用 GroovyObject#invokeMethod 执行类方法
一、GroovyObject 接口简介
在类中 , 如果没有实现某个 方法 或者 成员属性 , 可以利用 元编程 替换类中的 方法或属性 ;
在编译字节码文件时 , 每个 Groovy 类都会被编译成 GroovyObject 接口对象 ;
/** * 所有的 Groovy 类都要实现的接口 * <p> * 在Java世界中使用Groovy对象尤其方便。 */ public interface GroovyObject { /** * Invokes the given method. * * @param name 要执行的方法名 * @param args 方法调用方法参数 * @return 返回方法执行返回值 */ @Internal // 标记为内部只是为了向后兼容, e.g. AbstractCallSite.createGroovyObjectGetPropertySite 会检查 `isMarkedInternal` default Object invokeMethod(String name, Object args) { return getMetaClass().invokeMethod(this, name, args); } /** * 检索属性值。 * * @param propertyName 属性名称 * @return 返回查到的属性值 */ @Internal // 标记为内部只是为了向后兼容, e.g. AbstractCallSite.createGroovyObjectGetPropertySite will check `isMarkedInternal` default Object getProperty(String propertyName) { return getMetaClass().getProperty(this, propertyName); } /** * 将给定属性设置为新值。 * * @param propertyName 设置的属性名 * @param newValue 新属性 */ @Internal // 标记为内部只是为了向后兼容, e.g. AbstractCallSite.createGroovyObjectGetPropertySite will check `isMarkedInternal` default void setProperty(String propertyName, Object newValue) { getMetaClass().setProperty(this, propertyName, newValue); } /** * 返回给定类的元类。 * * @return 此实例的元类 */ MetaClass getMetaClass(); /** * 允许用派生实现替换元类。 * * @param metaClass 新的元类 */ void setMetaClass(MetaClass metaClass); }
二、MetaClass 简介
MetaClass 元类可以用于实现 元编程 的 方法注入 , 方法拦截 , 合成委托 等操作 ;
/** * Groovy中的元类定义任何给定Groovy或Java类的行为。 * 元类接口定义了两个部分。 * 客户端 API,它是通过ExtendeMetaObjectProtocol接口 * 和Groovy运行时系统的契约定义的。 * * 通常,编译器和Groovy运行时引擎与此类上的方法交互, * 而元类客户端与MetaObjectProtocol接口定义的方法交互 * * @see MetaClassImpl * @see groovy.lang.MetaObjectProtocol */ public interface MetaClass extends MetaObjectProtocol { }
三、使用 GroovyObject#invokeMethod 执行类方法
定义一个类 , 在其中定义 hello 方法 , 可以直接调用该方法 , 也可以通过 GroovyObject#invokeMethod 执行该方法 ;
代码示例 :
class Student { def name; def hello() { println "Hello ${name}" } } def student = new Student(name: "Tom") // 直接调用 hello 方法 student.hello() // 通过 GroovyObject#invokeMethod 调用 hello 方法 // 第二个参数是函数参数 , 如果为 void 则传入 null student.invokeMethod("hello", null)
执行结果 :
Hello Tom Hello Tom