2014-09-22 3 views
3

특정 작업을 자동화하기 위해 스크립트를 실행할 수있는 응용 프로그램이 있습니다. 이 스크립트에서 메타 프로그래밍을 사용하여 코드 크기와 가독성을 최적화하고 싶습니다. 그래서 대신 :Groovy의 metaClass 범위는 무엇입니까?

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

을 (그리고 나는 등 적절한 오류 처리를 할 수있는) :

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() 
    } 
} 

이 때문에 스크립트 작성자가 쓸 수 싶습니다.

이제 언제 어떻게 구현할 수 있을지 궁금합니다. 나는 모든 스크립트 앞에 붙이는 헤더에 메타 클래스의 조작을 첨부 할 수 있지만 두 명의 사용자가 동시에 (메타 클래스에 대한 동시 액세스) 스크립트를 실행하면 어떻게 될지 걱정됩니다.

메타 클래스의 범위는 무엇입니까? 컴파일러? 스크립트 환경? Java VM은 무엇입니까? Groovy를로드 한 클래스 로더?

내 생각에 Groovy 메타 클래스에 VM 범위가있는 경우 시작 중에 설치 스크립트를 한 번 실행할 수 있습니다.

파일 /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') 

그리고 (범위가 지정된 메타 클래스를 테스트하는 스크립트

+0

'try : ... finally :'? 파이썬이야? – Will

+0

@WillP : 좋은 캐치 :-) 고정. –

답변

3

메타 클래스는 클래스 로더 당 [표창장은 필요로했다] 존재 /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() 
     } 
    } 
} 

그들은 단지에 필요한 확장을 사용하는 사람을 위해 ... 그리고

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

을 그 컴파일 같은 것을 포함 META-INF/services/org.codehaus.groovy.runtime.ExtensionModule에서 파일을 포함하는 jar 파일에 넣어 CLASSPATH에 jar 파일을 넣으십시오. 대신에이 모든으로, 사용자는 확장 모듈에

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

자세한 내용은 http://docs.groovy-lang.org/docs/groovy-2.3.6/html/documentation/#_extension_modules에서 확인할 수있다 ... 같은 것을 할 수 있습니다.