`
xiefeifeihu
  • 浏览: 97312 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Groovy元编程MOP(ExpandoMetaClass:EMC)的应用场景

阅读更多

使用ExpandoMetaClass和Category可以实现元编程。ExpandoMetaClass可以动态添加和修改类的构造器,方法和属性。Category只能动态添加和修改类的方法。

当使用EMC动态添加或修改方法时,闭包Closure作为方法体被传入,它的delegate指向调用此方法的实例。

具体使用可参考:http://www.groovyq.net/node/75

 

1、为类添加方法(为String类添加String times(int count)方法)

    String.metaClass.times = {int count ->
            String str = ""
            for (int i = 0; i < count; i++) {
                str += delegate
            }
            return str
        }
        assert "hellohellohello", "hello".times(3)
2、为类添加重载方法(为String类添加String times()方法)
    String.metaClass.times << {->
            return delegate
        }
 
3、为类修改方法(将String类的toUpperCase改成toLowerCase)
    String.metaClass.toUpperCase = {->
            return delegate.toLowerCase()
        }
        assert "hello", "heLLO".toUpperCase()

4、反射拿到方法的元型
    String.metaClass.invokeMethod = {String mName, mArgs ->
            def m = String.metaClass.getMetaMethod(mName, mArgs)
            if (mName != "concat" && mName != "toUpperCase") return m.invoke(delegate, mArgs)
            long s = System.currentTimeMillis();
            def result = m.invoke(delegate, mArgs)
            long e = System.currentTimeMillis();
            long duration = e - s;
            println("MOP耗费时间:" + duration);
            return result;
        }
5、为单个实例添加或修改方法
    String instance = "hi"
        instance.metaClass.times = {int count ->
            String str = ""
            for (int i = 0; i < count; i++) {
                str += delegate
            }
            return str
        }

        println instance.times(3)
        println "he".times(3)      // MissingMethodException

6、一次添加多个方法
    String.metaClass {
            times {int count ->
                String str = ""
                for (int i = 0; i < count; i++) {
                    str += delegate
                }
                return str
            }
            toUpperCase {->
                return delegate.toLowerCase()
            }
        }
7、添加或修改静态方法(为String类添加static String twice(String val))
    String.metaClass.static.twice = {String val ->
            return val + val
        }
        assert "hellohello", String.twice("hello")

8、添加或修改构造器
class MOP {
        String val

        def print() {
            println val
        }
    }

    MOP.metaClass.constructor << {String val ->
            return new MOP(val: val)
        }

    new MOP("hello").print()

9、为类添加属性
MOP.metaClass.title = "title"
10、为类添加只读属性(即只添加get方法)
MOP.metaClass.getTitle = {-> "title"}
11、去掉元编程,只需将metaClass置为null即可
String.metaClass = null
12、可以在使用static方法时,用use块简化代码
    use(org.apache.commons.lang.time.DateUtils) {
            new Date().addDays(1) //这里实际调用的是static Date addDays(Date date,int amount)方法
    }
也可以一次使用多个类的static方法
    use(org.apache.commons.lang.time.DateUtils,org.apache.commons.lang.StringUtils) {
            new Date().addDays(1)
            "stringUtils".capitalise()
        }

既然EMC提供了运行期动态添加修改方法和属性的能力,我们可以用在什么地方呢?
1、有时候为了调试经常会调用System.out.println(XXXX),每次写这么长太烦了,如果变成XXXX.out()是不是就方便多了。
只需要为String、Integer等类添加一个out方法即可实现:
    String.metaClass.out = {->
            System.out.println(delegate)
        }
        "hello".out()
2、有时候为了从url获取数据(http GET方法),要是使用HttpClient得写一堆代码,如果变成调用"$url".httpGet()能直接获取响应报文该多爽啊。
其实只需要给String添加一个httpGet方法即可:
String.metaClass.httpGet = {->
//用HttpClient实现
}
3、同样在实现执行系统命令的时候也可以这么做。类似这种需求是无穷无尽的,都可以用MOP简单实现。
3.times { println "hello!" }
list << "a string"
def range = 1..9
。。。。。。
Groovy里面这些看似很神奇的语法其实都是通过MOP实现的。
4、用MOP实现AOP
用MOP可以实现方法拦截,对源代码丝毫没有侵入性。比如想知道String的toUpperCase方法执行效率就可以用MOP。也可以捕获异常输出到日志中,而不影响源代码的执行。
但是需要注意,如果应用层是用反射调用执行的,MOP就拦截不到了。
5、配置开关
比如系统要构建xml,调试时为了xml语意清晰可以在生成xml时加上comment备注,但是系统上线真正运营时这些comment就没什么用了,这时可以用MOP关掉commment。具体代码自己实现。
可以将这个功能写成一个函数,系统启动是调一下这个函数就关闭comment了。函数调用可以用Spring类配置。这样就可以用配置方式实现功能开关了。

 

6、DSL(略)

 

还有更多的应用场景,希望大家一块讨论。

2
3
分享到:
评论
1 楼 alanland 2013-05-06  
用起来还真是方便 ~ ~

相关推荐

    Groovy MOP

    Groovy MOP代码示例,利用Groovy的MOP机制动态热切入。

    groovy-3.0.9-API文档-中文版.zip

    Maven坐标:org.codehaus.groovy:groovy:3.0.9; 标签:groovy、codehaus、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码...

    Flutter 出现Could not download groovy-all.jar (org.codehaus.groovy:groovy-all:2.4.15)

    在一次代码拉取中,出现了以下问题:Could not download groovy-all.jar (org.codehaus.groovy:groovy-all:2.4.15) 详细的报错信息如下: // 报错信息如下 Could not resolve all files for configuration ':jcore-...

    [Groovy] Making Java Groovy 英文版

    Making Java Groovy is a practical handbook for developers who want to blend Groovy into their day to day work with Java It starts by introducing the key differences between Java and Groovy and how you...

    Groovy+Java混合使用例子

    Groovy环境搭建教程中的例子工程,纯Java、纯Groovy以及Java+Groovy混合 教程参考:http://blog.csdn.net/rcom10002/archive/2011/06/26/6568557.aspx

    apache-groovy-sdk-3.0.3.zip

    最新版本的groovy3.0.3,对groovy及gradle使用有兴趣的可以下来试用,为大家提供优秀资源,自己也赚点积分。

    [Groovy] Groovy 2 编程 (英文版)

    [Pragmatic Bookshelf] Groovy 2 编程 (英文版) [Pragmatic Bookshelf] Programming Groovy 2 Dynamic Productivity for the Java Developer (E-Book) ☆ 出版信息:☆ [作者信息] Venkat Subramaniam [出版机构...

    groovy-all-2.4.15.jar

    org.gradle.api.resources.ResourceException: Could not get resource '...下载groovy-all-2.4.15.jar后,放入对应的 android-studio/gradle/gradle-5.*/lib/目录。 重启 Android Studio 及可使用。

    Groovy高效编程

    Groovy语言。 里面详细介绍了一些很有意思的方法。

    groovy入门编程

    groovy入门 groovy入门 groovy入门 groovy入门groovy入门groovy入门

    groovy-2.5.1-API文档-中文版.zip

    Maven坐标:org.codehaus.groovy:groovy:2.5.1; 标签:codehaus、groovy、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码...

    groovy-3.0.9-API文档-中英对照版.zip

    Maven坐标:org.codehaus.groovy:groovy:3.0.9; 标签:groovy、codehaus、jar包、java、中英对照文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的...

    groovy-all-2.4.5-API文档-中文版.zip

    Maven坐标:org.codehaus.groovy:groovy-all:2.4.5; 标签:codehaus、groovy、all、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,...

    groovy-all-2.4.13-API文档-中文版.zip

    Maven坐标:org.codehaus.groovy:groovy-all:2.4.13; 标签:all、groovy、codehaus、jar包、java、API文档、中文版; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化...

    groovy-all-2.4.15.jar.zip

    groovy-all-2.4.15.jar文件,MAC使用时需存放在/Users/用户名/.gradle/caches/jars-3/某一缓存目录下,找不到就都看一下,我遇到的问题是缓存目录中下载的是2.4.17版本,应该跟gradle版本升级有关

    groovy-2.5.1-API文档-中英对照版.zip

    Maven坐标:org.codehaus.groovy:groovy:2.5.1; 标签:codehaus、groovy、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的...

    apache-groovy-sdk-2.5.0-beta-2.zip

    Groovy 2.5 is the upcoming version of Groovy. For the sdk 截至2017.11.09 groovy最新最稳定版本 大小:60.0 MB

Global site tag (gtag.js) - Google Analytics