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 元类的范围?的主要内容,如果未能解决你的问题,请参考以下文章