Groovy 元对象协议Mop(一)

  |   0 评论   |   0 浏览

在java中,我们可以在运行时探索程序的结构,以及程序的类和方法,方法接收的参数等。然后我们仍然局限于所创建的静态结构,我们无法在运行时修改一个对象的类型,或是让他动态获取行为。如果我们可以基于应用当前的输入,动态的添加方法和行为,代码会变得更加灵活。我们的创造力和开发效率将大大提升。那么,Groovy就提供了这种功能。

概念

元编程(metaprogramming)意味着编写能够操作程序的程序。包括程序自身。像Groovy这样的动态语言通过元对象协议(MetaObject Protocol, MOP),提供了这种能力。

利用MOP能够干什么呢

利用Groovy的MOP,创建类、编写单元测试和引入模拟对象都很容易。
在groovy中,利用MOP可以动态的调用方法,甚至在运行时合成类和方法。这种特性给我们的感觉就是对象顺利的修改了他的类。比如Grails和GORM就使用了该特性,为数据查询合成方法,借助Mop,在Groovy中可以创建内部的领域特定语言。

这篇文章我们先讨论Groovy对象的组成。

Groovy对象的组成

Groovy对象是带有附加功能的Java对象。在Groovy中,Groovy对象比编译好的Java对象具有更多的动态行为。此外对于Java对象和Groovy对象上的方法调用,Groovy的处理方式也是不同的。

在一个Groovy应用中,我们会使用三类对象,POJO、POGO、Groovy拦截器。POJO就是普通的Java对象,可以使用Java或者JVM上的其他语言来创建。POGO是Groovy编写的对象。它扩展了java.lang.object,同时也实现了groovy.lang.GroovyObject接口。Groovy拦截器是扩展了GroovyInterceptable的Groovy对象。具有方法拦截功能.
Groovy定义的GroovyObject接口:

package groovy.lang;
import groovy.lang.MetaClass;
public interface GroovyObject {
    Object invokeMethod(String var1, Object var2);
    Object getProperty(String var1);
    void setProperty(String var1, Object var2);
    MetaClass getMetaClass();
    void setMetaClass(MetaClass var1);
}

invokeMethod()、getProperty()、setProperty()使得java对象有了高度的动态性。可以使用它们来处理运行时创建方法和属性。

再看一下GroovyInterceptable接口,它是一个扩展了GroovyObject的标记接口,对于实现了该接口的对象而言,其上的所有的方法调用,都会被它的invokeMethod方法拦截

public interface GroovyIntercptable extends GroovyObject {
}

看个例子

class InvokeMethodTestor {
   deftest() {
       println'hello,function name is test'
   }
    def invokeMethod(String name,Object args) {
       println"the other function, name is ${name}"
    }
}

这是一个很简单的Groovy类,我们有一个test方法,用来向控制台打印一句话;然后我们实现了invokeMethod方法,并且把参数“name”打印在控制台。
在讲述“invokeMethod”方法的作用之前,我们先来测试一下上面的类。

def testor = new InvokeMethodTestor()
testor.test()
testor.hello()
testor.doSomething()

我们先来看看测试结果:

hello,function name is test
the other function, name is hello
the other function, name is doSomething

通过测试结果,我们可以看出,语句“testor.test()”调用了“InvokeMethodTestor”类的“test”方法,而语句“testor.hello()”和“testor.doSomething()”却都调用了“InvokeMethodTestor”类的“invokeMethod”方法。
这就告诉我们,对于一个实现了“invokeMethod”方法的Groovy类的对象,可以执行任意的方法,如果该方法已经在该类中实现,就调用该方法,如“testor.test()”就调用“InvokeMethodTestor”类的“test”方法;如果该方法没有在该类中实现,如“testor.hello()”和“testor.doSomething()”,就调用该类的“invokeMethod”方法。
这样说来,“invokeMethod”方法其实蛮简单的,一点都不神秘和麻烦。但是它的作用却一点都不能小觑,它给我们的Groovy语言编程带来了很大的动态性。