使用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()
}
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->
既然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(略)
还有更多的应用场景,希望大家一块讨论。
分享到:
相关推荐
6. **MetaProgramming in Practice**: 在实际开发中,Groovy MOP可以用于AOP(面向切面编程)、日志记录、性能监控、事务管理等多种场景。例如,你可能想要在所有数据库操作前后插入日志记录,或者在执行某些高风险...
MOP(MetaObjectProtocol,元对象协议)是Groovy中元编程的基础框架。它定义了一组接口和方法,使得我们可以通过这些接口和方法来操纵对象的元数据,从而实现动态方法调用、属性访问等。MOP使得Groovy具备了强大的...
文档可能会详细解释如何使用类别和闭包来添加新方法,以及元编程的概念,如MetaClass和ExpandoMetaClass。 5. **Groovy的Web开发**:Groovy在Web开发中的应用,如构建RESTful服务、使用Grails框架开发全功能Web应用...
3. **元编程**:Groovy支持元编程,允许在运行时修改或扩展对象的行为。这通过MetaClass机制实现,可以在运行时添加方法或者属性,极大地增强了代码的灵活性。 4. **闭包(Closures)**:Groovy中的闭包是其核心...
Maven坐标:org.codehaus.groovy:groovy:3.0.9; 标签:groovy、codehaus、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码...
Maven坐标:org.codehaus.groovy:groovy-all:2.4.5; 标签:codehaus、groovy、all、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译...
Groovy是一种动态、开源的编程语言,它是Java平台上的一个重要的补充。Groovy结合了Python、Ruby和Smalltalk等语言的特性,同时保留了与Java的无缝集成能力,使得它在脚本编写、Web开发、自动化测试等领域有着广泛的...
在一次代码拉取中,出现了以下问题:Could not download groovy-all.jar (org.codehaus.groovy:groovy-all:2.4.15) 详细的报错信息如下: // 报错信息如下 Could not resolve all files for configuration ':jcore-...
Groovy 脚本化Bean jar包下载
Groovy API 学习文档是针对Groovy编程语言的一个重要参考资料,它包含了Groovy语言的API接口、类库以及各种工具的详细说明。Groovy是一种动态、灵活的面向对象编程语言,它在Java平台上运行,并与Java代码无缝集成。...
Groovy SDK 4.0.3 是一个针对Groovy编程语言的软件开发工具包,它包含了Groovy语言的运行环境和开发所需的各种组件。Groovy是一种动态、灵活的面向对象编程语言,它与Java语法兼容,但提供了更简洁的语法和更强的...
Groovy不仅支持静态类型检查,还可以在运行时动态地编译和执行代码,这使得它在Java平台中的应用场景非常广泛。本文将详细介绍Groovy脚本的基本概念、特点、用途以及如何在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...
- **元对象协议(MOP)**:Groovy的元对象协议允许在运行时扩展对象的行为。 - **类别(Category)**:类别可以为任何类添加方法,提供一种便捷的扩展机制。 4. **Groovy的脚本支持**: - **脚本执行**:Groovy...
Groovy是一种基于Java平台的、动态的、强大的编程语言,它融合了面向对象编程、函数式编程和静态类型检查的能力,为开发者提供了简洁、高效的语法,使得编写Java虚拟机(JVM)上的应用程序变得更加容易和快捷。...
Groovy是一种基于Java平台的动态编程语言,它与Java语法高度兼容,但提供了更简洁、更灵活的语法,使得开发更为高效。Groovy基础教程源码涵盖了Groovy语言的各个方面,是学习和理解Groovy语言的宝贵资源。下面将详细...
3. **元编程**:Groovy允许在运行时修改类和对象的行为,这是通过元对象协议(Meta Object Protocol, MOP)实现的,它增强了动态语言的能力。 4. **集成Java**:由于Groovy运行在JVM上,它可以无缝地与Java代码交互...
Groovy是一种基于JVM的动态编程语言,它简化了Java的语法并增加了许多便利特性。Groovy的RESTClient库是一个强大的工具,用于发送HTTP请求并处理响应,这对于与CouchDB进行交互非常实用。RESTClient库支持GET、POST...