`
jimichan
  • 浏览: 278235 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

groovy MetaClass 剖析 1

阅读更多

<!----><!---->

本篇介绍groovy 的MetaClasses ,MetaClass 是Groovy 动态编程比较重要的组成。

(以下出现的代码片段是在groovy1.5.3测试通过,希望各位可以运行之)。

 

1.MetaClass

           groovy中出现的每个类都有其对应的MetaClass。MetaClas是一个接口,该接口扩展了MetaObjectProtocol接口,这就是我们通常所说的MOP协议了。

MetaClass的实现类主要有 

 

 

MetaClassImpl 是通用的实现类。ClosureMetaClass是闭包类特有的MetaClass。ExpandoMetaClass是用户扩展groovy类行为时用到的MetaClass

 

println 'first:---> '+'test'.metaClass

println 'String.metaClass:---> '+String.metaClass

println 'after String.metaClass:--->  '+'test'.metaClass

 

执行结果为
first:---> groovy.lang.MetaClassImpl@183f74d[class java.lang.String]
String.metaClass:---> groovy.lang.ExpandoMetaClass@8a0d5d[class java.lang.String]
after String.metaClass:--->  groovy.lang.ExpandoMetaClass@8a0d5d[class java.lang.String]

 对于这样的结果你是不是会感觉到奇怪呢?

下面我将结合Groovy实现代码来解释这个过程

第一句脚本 通过String实例对象来获得,Groovy为其初始化的groovy.lang.MetaClassImpl@183f74d[class java.lang.String]对象。这个对象将在MetaClassRegistryImpl中和String类关联起来。也就是注册了String.class和

groovy.lang.MetaClassImpl的对象关系。

第二句脚本 通过String类去访问 metaClass对象,不过这一次是调用了类DefaultGroovyMethods中的方法

 

    /**
     * Adds a "metaClass" property to all class objects so you can use the syntax
     * <code>String.metaClass.myMethod = { println "foo" }</code>
     *
     * @param c The java.lang.Class instance
     * @return An MetaClass instance
     */
    public static MetaClass getMetaClass(Class c) {
        MetaClassRegistry metaClassRegistry = GroovySystem.getMetaClassRegistry();
        MetaClass mc = metaClassRegistry.getMetaClass(c);
        if (mc instanceof ExpandoMetaClass
                || mc instanceof DelegatingMetaClass && ((DelegatingMetaClass) mc).getAdaptee() instanceof ExpandoMetaClass)
            return mc;
        else {
            MetaClass emc = ExpandoMetaClassCreationHandle.instance.create(c, metaClassRegistry);
            emc.initialize();
            metaClassRegistry.setMetaClass(c, emc);//并且在metaClassRegistry中注册
            return emc;
        }
    }

 第三句脚本又重新通过String实例对象来获得了,但这一次得到的是groovy.lang.ExpandoMetaClass@8a0d5d,这是因为第二句话中对String和其MetaClass对象进行了重新注册。

自此以后系统中所有的String对象的MetaClass对象都一直市是ExpandoMetaClass对象实例。

 

 

由于我们举的String例子有点特殊

我们看看对于自定义类的例子

class Foo{
	
}
def f1 = new Foo();
println f1.metaClass

println Foo.metaClass

println f1.metaClass

def f2 = new Foo()
println f2.metaClass

 结果是不是又不一样了?

f1对象的metaClass是被缓存了,只有在调用过

Foo.metaClass

 之后,new出来的对象才会使用ExpandoMetaClass

 

 

2
0
分享到:
评论
6 楼 jimichan 2008-11-11  
就我所知,系统类如内置数组类的处理方式是不一样的
5 楼 bloodwolf_china 2008-11-07  
那为什么'test'的metaClass没有被缓存,f1 = new Foo(); f1对象的metaClass就
缓存呢?
'test'.metaClass --MetaClassImpl
String.metaClass --ExpandoMetaClass
'test'.metaClass --ExpandoMetaClass

f1 = new Foo();
f1.metaClass --MetaClassImpl
Foo.metaClass --ExpandoMetaClass
f1.metaClass --MetaClassImpl
系统类和自定义类处理不一样?
4 楼 RayChase 2008-10-27  
好久了吧 剖析2还没出啊 呵呵
3 楼 jimichan 2008-09-25  
最近觉得学习这个语言的话,没有太多必要研究底层如何实现的
2 楼 RayChase 2008-09-21  
期待剖析2
1 楼 RayChase 2008-09-21  
有收获!

相关推荐

Global site tag (gtag.js) - Google Analytics