12.2Groovy使用MetaClass拦截方法

来源:互联网 发布:游戏神作 知乎 编辑:程序博客网 时间:2024/05/18 00:47

在要拦截类的外部,以闭包的形式,增加MetaClass的invokeMethod()方法,这种方式适合我们无权修改的源代码。

class Car{ // 不用实现GroovyInterceptable接口    def check(){System.out.println "check called..." } // 检查    def start(){System.out.println "start called..." } // 启动    def drive(){System.out.println "drive called..." } // 驾驶}// 在类Car的外面,以闭包的形式,添加(或者叫定义)invokeMethod()方法Car.metaClass.invokeMethod = {String name, args ->    System.out.print("call to $name intecepted...")    if(name!='check') {        System.out.print("running filter...")        Car.metaClass.getMetaMethod('check').invoke(delegate, null) // 是delegate非thisi    }    def validMethod = Car.metaClass.getMetaMethod(name, args)    if (validMethod != null) {        validMethod.invoke(delegate, args)    } else {        Car.metaClass.invokeMissingMethod(delegate, name, args) // 是invokeMissingMethod()非invokeMethod()    }}car = new Car()car.start()car.drive()car.check()try {    car.speed() // Car中不存在的方法} catch (Exception e) {    println e}

运行结果:

call to start intecepted...running filter...check called...
start called...
call to drive intecepted...running filter...check called...
drive called...
call to check intecepted...check called...
call to speed intecepted...running filter...check called...
groovy.lang.MissingMethodException: No signature of method: Car.speed() is applicable for argument types: () values: []
Possible solutions: sleep(long), sleep(long, groovy.lang.Closure), split(groovy.lang.Closure), check(), start(), grep()

上面拦截的是Groovy类,再看一个栗子,拦截Java类(POJO)Integer中的方法:

// 在Integer的MetaClass上添加invokeMethod()方法,拦截Integer上的方法。Integer.metaClass.invokeMethod = { String name, args ->    System.out.println("Call to $name intercepted on $delegate...")    def validMethod = Integer.metaClass.getMetaMethod(name, args)    if (validMethod == null) {        Integer.metaClass.invokeMissingMethod(delegate, name, args)    }else {        System.out.println("running pro-filter...")        result = validMethod.invoke(delegate, args)        System.out.println("running post-filter...")        result    }}println 5.floatValue()println 5.intValue()try {    println 5.empty() // Integer中不存在的方法} catch (Exception e) {    println e}

运行结果:

Call to floatValue intercepted on 5...

running pro-filter...

running post-filter...
5.0
Call to intValue intercepted on 5...
running pro-filter...
running post-filter...
5
Call to empty intercepted on 5...
groovy.lang.MissingMethodException: No signature of method: java.lang.Integer.empty() is applicable for argument types: () values: []
Possible solutions: every(), every(groovy.lang.Closure), upto(java.lang.Number, groovy.lang.Closure), wait(), any(), next()

--------------------------------------------------------------------------------------------------

可以在Groovy类中同时提供invokeMethod()方法和methodMissing()方法,invokeMethod()方法会优先于methodMissing方法使用。


阅读全文
0 0
原创粉丝点击