首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

MOP——方法注入(2)

MOP——方法注入(2)

使用 ExpandoMetaClass 进行方法注入
注入概述

之前其实我们已经见到过使用 ExpandoMetaClass 注入方法的示例了,就是使用MetaClass 进行方法拦截,这本质就是方法的注入,只不过注入的方法名(invokeMethod)比较特殊,成为了方法拦截。同样,我们也可以用 ExpandoMetaClass 对类进行其它方法的注入,还拿上面 Integer 的加法的例子:

    Integer.metaClass.add = {
        int i ->
            delegate + i
    }
     
    println 1.add(3)

注入的种类

使用 ExpandoMetaClass 方法注入,可以对以下三种方法进行注入:

    非静态方法
    静态方法
    构造器
    属性

接下来一一介绍如何注入:

    非静态方法注入
    这在前面已经见到过了,也是最常用的注入,使用方法:

    Foo.metaClass.bar = {}
    foo.bar()

Groovy 的设计理念就是让程序的编写更加流程,因此在 DSL 中,可能更常见的一种形式是在调用方法时不写括号,即foo.bar但是没有括号调用时,会将方法的调用当成属性,所以需要对之前的注入进行修改。

    Foo.metaClass.getBar = {}
    foo.bar

这样的调用方式是否更加优雅呢,在后面的 DSL 中,还会进一步讲解 groovy 的语法糖,让编程更加优雅。

    静态方法注入
    需要使用 'static' 的特殊字面量注入静态方法

    Foo.metaClass.'static'.bar = {}
    Foo.bar()

    注入构造器
    使用 constructor 属性注入构造器
    添加一个构造器 <<
    替换一个构造器 =

    Foo.metaClass.constructor << {
      int i ->
      Foo foo = new Foo();
      foo.i = i
      foo
    }

构造方法注入特别要注意的是,要确保没有递归调用自身,否则栈溢出。因为我们是想定义构造器,肯定会借助现有的构造器,然后进行属性的改造,但是不要产生递归。如果是想覆盖构造器的话,那么只能在内部使用反射

    注入属性
    类似以闭包的方式注入方法,属性注入也是支持的,只要在后面 = 具体值 即可。

    Foo.metaClass.bar = 1
    println foo.bar

    一次注入多个方法
    Groovy 提供了使用ClassName.metaClass.method = { ... }这样的语法向 metaClass 中添加,既简单又方便,但如果想添加一堆方法,这样的声明就会感觉很费劲。groovy 提供了更简洁的语法,用来减少噪音!!这种方式也是在 DSL 中常见到的。

    Foo.metaClass = {
      bar1 = {}
      bar2 = {}
     
      'static'{
          bar3 = {}
      }
      //针对于不管是覆盖还是注入,在这种语法环境下,都应该使用 =
      constructor = {
          int i - >
      }
     
      constructor = {
          int i,int j ->
      }
    }

再次重申:使用 ExpandoMetaClass 注入的闭包中,delegate 指的是调用该方法的对象,在此基础上,闭包中使用类原本的成员变量,或者方法也是可以的。
返回列表