Groovy 元类的范围?

Posted

技术标签:

【中文标题】Groovy 元类的范围?【英文标题】:Scope of Groovy's metaClass? 【发布时间】:2014-11-16 10:41:25 【问题描述】:

我有一个可以运行脚本来自动执行某些任务的应用程序。我想在这些脚本中使用元编程来优化代码大小和可读性。所以而不是:

try 
    def res = factory.allocate();
    ... do something with res ...
 finally 
    res.close()

我愿意

Factory.metaClass.withResource =  c -> 
    try 
        def res = factory.allocate();
        c(res)
     finally 
        res.close()
    

所以脚本作者可以写:

factory.withResource  res ->
    ... do something with res ...

(我可以进行适当的错误处理等)。

现在我想知道何时以及如何可以/应该实现这一点。我可以将元类的操作附加到每个脚本前面的标题中,但我担心如果两个用户同时运行脚本会发生什么(对元类的并发访问)。

元类的范围是什么?编译器?脚本环境? Java虚拟机?加载 Groovy 的类加载器?

我的理由是,如果 Groovy 元类具有 VM 范围,那么我可以在启动期间运行一次设置脚本。

【问题讨论】:

try: ... finally:?那是蟒蛇吗? @WillP: 不错 :-) 已修复。 【参考方案1】:

每个类加载器都有元类[需要引用]

文件/tmp/Qwop.groovy

class Qwop  

文件/tmp/Loader.groovy

Qwop.metaClass.bar =  
qwop1 = new Qwop()
assert qwop1.respondsTo('bar')

loader = new GroovyClassLoader()
clazz = loader.parseClass new File("/tmp/Qwop.groovy")

clazz.metaClass.brap =  'oh my' 

qwop = clazz.newInstance()

assert !qwop.respondsTo('bar')
assert qwop1.respondsTo('bar')

assert qwop.brap() == "oh my"
assert !qwop1.respondsTo('brap')

// here be custom classloaders
new GroovyShell(loader).evaluate new File('/tmp/QwopTest.groovy')

还有一个用于测试作用域元类的脚本 (/tmp/QwopTest.groovy):

assert !new Qwop().respondsTo('bar')
assert new Qwop().respondsTo('brap')

执行:

$ groovy Loaders.groovy 
$ 

如果您有一组定义明确的类,则可以根据添加的brap 方法在类由您的类加载器加载 之上应用元编程。

【讨论】:

【参考方案2】:

这种事情的另一种选择是使用扩展模块。

package demo

class FactoryExtension 
    static withResource(Factory instance, Closure c) 
        def res
        try 
            res = instance.allocate()
            c(res)
         finally 
            res?.close()
        
    

编译它并将其放入一个 jar 文件中,该文件包含一个位于 META-INF/services/org.codehaus.groovy.runtime.ExtensionModule 的文件,其中包含类似这样的内容...

moduleName=factory-extension-module
moduleVersion=1.0
extensionClasses=demo.FactoryExtension

然后,为了让某人使用您的扩展,他们只需将该 jar 文件放在他们的 CLASSPATH 中。有了所有这些,用户就可以做这样的事情......

factoryInstance.withResource  res ->
    ... do something with res ...

有关扩展模块的更多信息,请访问http://docs.groovy-lang.org/docs/groovy-2.3.6/html/documentation/#_extension_modules。

【讨论】:

以上是关于Groovy 元类的范围?的主要内容,如果未能解决你的问题,请参考以下文章

groovy 元类替换超类方法

Groovy 元类,模拟具有 throws 子句的服务方法

Groovy:在调用任何方法之前和之后透明地执行代码

如何知道日期范围是不是与Java中的另一个日期范围相交 - Groovy [重复]

如何在 Groovy 中动态覆盖类的“each”方法?

Groovy:为接口委托元类?