2014-10-23 1 views
4

주어진 GroovyShell 컨텍스트에서만 사용자 정의 IntegerMetaClass을 사용하고 싶습니다.GroovyShell에 IntegerMetaClass를 동적으로 추가하기

이유는 전체 런타임을 잠재적으로 '방해가되는'것으로 오염시키지 않는 이유입니다. IntegerMetaClass.

내 IntegerMetaClass.java 구현을 마법 패키지 groovy.runtime.metaclass.java.lang에 넣으면 매력적으로 작동합니다. 하지만 중간 GroovyClassLoader에 수동으로 추가하려고하면 작업이 중단됩니다.

// Pseudo-code without try catch, etc 
// Within my eval factory 
GroovyClassLoader gcl = new GroovyClassLoader(getClass().getClassLoader()); 
URL url = getClass().getClassLoader().getResource("groovy/runtime/metaclass/java/lang/IntegerMetaClass.groovy"); // I rename it to .groovy file 
GroovyCodeSource gcs = new GroovyCodeSource(url); 
Class<?> clazz = gcl.parseClass(gcs); 
// clazz is not null here and equals to what I expect: 
// Class<groovy.runtime.metaclass.java.lang.IntegerMetaClass> 

// Now trying to use it in a groovy shell 
GroovyShell gs = new GroovyShell(gcl); 
gs.evaluate("10.minutes"); // Where .minutes is part of my IntegerMetaClass 
// Fail with an NoSuchProperty exception 

난 그냥 메타 클래스를 '분석'보다 더 GroovyClassLoader에 할 수있는 뭔가를 그리워합니까? 다른 곳 ?

갱신 1 : 내 자바 소스 클래스 경로에 직접 넣을 때 위에서 언급 한 바와 같이

IntegerMetaClass.minutes 조회 노력하고 있습니다.

package groovy.runtime.metaclass.java.lang; 

import groovy.lang.DelegatingMetaClass; 
import groovy.lang.MetaClass; 

public class IntegerMetaClass extends DelegatingMetaClass { 
    public IntegerMetaClass(Class<Integer> delegate) { 
     super(delegate); 
    } 

    public IntegerMetaClass(MetaClass delegate) { 
     super(delegate); 
    } 

    @Override 
    public Object getProperty(Object object, String property) { 
     if ("minutes".equals(property)) { 
      Integer q = (Integer) object; 
      return new Minutes(q); 
     } 
     return super.getProperty(object, property); 
    } 
} 

갱신 2 :

가능한하지만 만족하지 솔루션 : 추가

다음 바로 gcl.parseClass 호출 후

Constructor<?> constructor = clazz.getConstructor(Class.class); 
DelegatingMetaClass dmc = (DelegatingMetaClass) constructor.newInstance(Integer.class); 
dmc.initialize(); 
InvokerHelper.getMetaRegistry().setMetaClass(Integer.class, dmc); 

그러나이 솔루션은 일종의을 유지한다이상을 지원하기 위해 MetaClass 소스와 원래의 대상 클래스 간의 '매핑' IntegerMetaClass는 끝내 파일 때 나는 java.lang.IncompatibleClassChangeError을 가지고 있지만, 자바는 아무 문제 없을 때 :

GroovyShell gs = new GroovyShell() 
    gs.loader.loadClass('groovy.runtime.metaclass.java.lang.IntegerMetaClass') 
    gs.evaluate("10.minutes") 

참고 : 0 ...

+0

'IntegerMetaClass' 소스를 게시 할 수 있습니까? – Will

+0

관련 항목 : http://stackoverflow.com/questions/25974525/scope-of-groovys-metaclass –

+0

문제는 내가 평가 한 그루비 스크립트를 쓰는 사용자가 '메타 설정'클래스를 사용하기 전에 걱정하지 않기를 바란다. . –

답변

1

당신은 GroovyShell 클래스 로더와 클래스를로드 할 수 있습니다. 내 환경 설정과 관련이있을 수 있습니다.

관련 문제