2014-12-10 3 views
0

제가 알고 있듯이 Java로 Groovy 스크립트를 컴파일하는 방법은 최소한 두 가지가 있습니다.컴파일 된 Groovy 스크립트

  1. CompiledScript으로 변환하려면 javax.script.ScriptEngine을 사용하십시오.

    ScriptEngine engine = new ScriptEngineManager().getEngineByName("Groovy"); 
    
    Bindings bindings = new SimpleBindings(); 
    bindings.put("foo", 1234); 
    
    Compilable compEngine = (Compilable)engine; 
    CompiledScript cs = compEngine.compile("if (foo == 1234) true else false"); 
    cs.eval(bindings); 
    
  2. 사용 GroovyClassLoader#parse, 일부 중간 일을하고 GroovyObject#invokeMethod(String, Object[])를 호출합니다.

주 - 다음 코드는 Groovy in Action입니다. Groovy를 배우기에 훌륭한 책이라는 것을 알게되었습니다. 값으로 변수 이름 - 나는이 두 방식의 차이점을 알고있는 것처럼

GroovyClassLoader gcl = new GroovyClassLoader(); 
// Note, assume that the Groovy script gets compiled to a class that 
// includes a method, "do". And "do" accepts an `Integer` argument, "foo." 
Class foo    = gcl.parseClass("if (foo == 1234) true else false"); 
GroovyObject hello = (GroovyObject) foo.newInstance(); 
Object[] args   = { Integer.valueOf(1234) }; 
assert     true == (foo.invokeMethod("do", args)); 

은, 첫 번째는 key-value쌍와 Bindings지도를 채우는 포함한다. 그런 다음 Bindings 인수가 변형 된 CompiledScript#eval(Bindings)을 통해 CompiledScript을 실행합니다.

그러나 Foo 클래스 개체를 메서드 Foo#do에 전달하려고한다고 가정 해 보겠습니다. 그리고 if (foo == 1234) ...을 평가하기보다는 소스 코드에서 다음과 같이 작성해야합니다.

if(fooObj.getFoo() == 1234) ....

그러면 결과적으로 후 처리 올바른 방법을 포함하여 foo에 도착해야합니다.

일반적으로 위의 예에 따라 두 번째 방법을 구현하는 간단한 방법이 있습니까?

답변

1

실제로 두 가지 옵션이 있습니다. 이 모든 것은 문서 (http://docs.groovy-lang.org/2.3.8/html/documentation/#_integrating_groovy_in_a_java_application 참조)에 설명되어 있지만, JSR-223 (javax.script)은 매우 불충분 한 통합 메커니즘이므로 사용하지 않는 것이 좋습니다. 예를 들어 GroovyShell 또는 GroovyClassLoader를 사용

, 당신은 매우 쉽게 foo 인스턴스를 설정할 수 있습니다 것 자신의 기본 스크립트 클래스를 설정할 수 있습니다,하지만 당신은 또한 당신의 기본 스크립트 클래스의 메서드를 호출 할 수있다.

현재 모든 Groovy 스크립트가 구현하는 방법은 do이 아니라 run입니다. 이 같은 Foo에 대한

public abstract class MyDSL extends groovy.lang.Script { 
    Object fooObj 
    public void setFooObj(Object foo) { fooObj = foo; } 
    public Object getFooObj() { return fooObj; } 
} 

및 홀더 클래스 : 그래서 당신은 다음과 같은 기본 클래스가 상상

public class FooHolder { 
    def getFoo() { return 1234; } 
} 

당신은 스크립트 이런 식으로 만들 수 있습니다

CompilerConfiguration config = new CompilerConfiguration(); 
config.setScriptBaseClass("test.MyDSL"); 
GroovyClassLoader gcl = new GroovyClassLoader(this.getClass().getClassLoader(),config); 
Class<? extends MyDSL> scriptClass = gcl.parseClass("return (fooObj.getFoo()==1234)"); 
MyDSL v1 = scriptClass.newInstance(); 
v1.setFooObj(new FooHolder()); 
Object result = v1.run(); 

주를이 이것은 실제로이 작업을 수행하는 한 가지 방법이지만 사용자의 필요에 맞는 최상의 방법은 아닙니다. 어쩌면 당신이 원하는 것을 조금 더 설명 할 수 있지만, Groovy는 이와 같은 스크립트를 컴파일하는 것부터 자신의 클래스 나 인터페이스를 확장하는 클래스를 컴파일하는 것까지 많은 옵션을 가지고 있습니다. 문서를보고 저희에게 알려주십시오.

+0

기본적으로 Java에서 Groovy 스크립트를 호출합니다.'CompiledScript'에 대해 제가 좋아하는 것은 제가 쉽게 재사용 할 수 있다는 것입니다. 'Class' 접근 방식으로, 실제 Groovy DSL 스크립트를 올바른 클래스로 수정해야합니다. 그러나'CompiledScript' 접근법을 사용하면 Groovy DSL을 그대로 유지할 수 있습니다. 그런 다음'CompiledScript # eval (Bindings) '을 호출하여 평가할 수 있습니다. –

+0

'Script' 클래스에는 이미'Binding' 인스턴스가 포함되어 있으므로 아무것도하지 않아도됩니다. 새 인스턴스를 만들지 않으면 스레드로부터 안전하지 않습니다. – melix

+0

만약'Bindings'의'당신이 새로운 인스턴스를 만들지 않는다면, 당신은 thread safe가 아닙니다 -'? –

관련 문제