2014-10-05 10 views
6

Ich möchte Dynamic Languages Support von Spring Framework verwenden.Spring Dynamic Languages ​​Unterstützung von Java-Konfiguration

In XML würde ich nur verwenden, um die lang Namespace, aber ich möchte Java-Konfiguration verwenden (das heißt @Configuration Klassen) nur.

Ich kann mir vorstellen, dass ich es durch die Initialisierung der Hölle von org.springframework.scripting.config Paket, Inc. tun kann. alle BeanPostProcessor s, Handler s, Parser s und FactoryBean s sie schaffen, aber ich wirklich will nicht dorthin gehen.

Gibt es einen anderen Weg? Wenn es keine gibt, welche minimale Konfiguration wird benötigt, um aus einem Groovy-Skript eine neu ladbare Bean zu erstellen?

Antwort

5

Warum fragen Sie uns nicht direkt per E-Mail? :-)

Ich sehe, dass XML Lang Unterstützung ist Magie. Es gibt genug Zeug, das auf BeanDefinition und seiner attributes basiert. Zusätzlich gibt es einige Haken mit ProxyFactory und CGLIB für die lang:property.

Was sehe ich für die JavaConfig ist einige Java-Klasse-Wrapper für die ScriptEvaluator und RefreshableResourceScriptSource von Spring Integration:

@ContextConfiguration 
@RunWith(SpringJUnit4ClassRunner.class) 
public class RefreshableScriptJavaConfigTests { 

    @Autowired 
    private Calculator calculator; 

    @Test 
    public void testGroovyRefreshableCalculator() { 
     assertEquals(5, this.calculator.add(2, 3)); 
    } 

    @Configuration 
    public static class ContextConfiguration { 

     @Value("classpath:org/springframework/integration/scripting/config/jsr223/Calculator.groovy") 
     private Resource groovyScriptResource; 

     @Bean 
     public ScriptEvaluator groovyScriptEvaluator() { 
      return new GroovyScriptEvaluator(); 
     } 

     @Bean 
     public Calculator calculator() { 
      return new Calculator(new RefreshableResourceScriptSource(this.groovyScriptResource, 1000)); 
     } 

    } 

    public static class Calculator { 

     private final ScriptSource scriptSource; 

     @Autowired 
     private ScriptEvaluator scriptEvaluator; 

     public Calculator(ScriptSource scriptSource) { 
      this.scriptSource = scriptSource; 
     } 

     public int add(int x, int y) { 
      Map<String, Object> params = new HashMap<String, Object>(); 
      params.put("x", x); 
      params.put("y", y); 
      return (int) this.scriptEvaluator.evaluate(this.scriptSource, params); 
     } 

    } 

} 

Wo die Calculator.groovy ist:

x + y 

Ich verstehe, dass es nicht so ist Flexibel, wie es mit Schnittstellen und Konfiguration aus XML-Definition aussieht, aber zumindest wird es Ihnen helfen, zu sehen, wo wir sind.

Fühlen Sie sich frei, ein JIRA-Problem in Bezug auf die Angelegenheit zu erheben, und wir werden sehen, was wir hier tun können. So etwas wie @EnableScripting und @ScriptSource(refreshDelay = 1000) über die Resource@Bean Methode.

Ich denke für jetzt können Sie nur @Import einige XML-Schnipsel mit lang Definitionen.

Cheers, Artem

+0

Vielen Dank für Ihre Antwort, Mann! Ich habe nicht per E-Mail Ursache 1 gefragt. Ich denke, es ist eine gute Q & A zu öffentlich und auffindbar, 2. Boom, Sie haben nur +25 rep :) Es ist nicht so schlimm, ich muss sagen, ich habe schlimmer erwartet. Und ja, '@ EnableScripting' ist der Weg, ich werde eine Feature-Anfrage hinzufügen. – JBaruch

+0

https://jira.spring.io/browse/SPR-12300 Glückszahl :) – JBaruch

1

Ich werde down the same path (work in progress), und haben es geschafft, indem man die Bohne Definitionen aufladbare Groovy Skripte zu initialisieren, wenn der Frühling Anwendung hergestellt wird. In meinem Beispiel verwende ich spring-boot.

Wenn Sie die folgende AddBeanDefinitionsListener Listener-Klasse und eine ScriptFactoryPostProcessor Bohne hinzufügen, können Sie Groovy-Skripte mit sehr wenig Aufwand ...

AddBeanDefinitionsListener.groovy

public class AddBeanDefinitionsListener 
     implements ApplicationListener<ApplicationPreparedEvent> { 

    Map<String, BeanDefinition> beanDefs 

    AddBeanDefinitionsListener(Map<String, BeanDefinition> beanDefs) { 
     this.beanDefs = beanDefs 
    } 

    @Override 
    void onApplicationEvent(ApplicationPreparedEvent event) { 
     def registry = (BeanDefinitionRegistry) event.applicationContext 
       .autowireCapableBeanFactory 
     beanDefs.each { String beanName, BeanDefinition beanDef -> 
      registry.registerBeanDefinition(beanName, beanDef) 
     } 
    } 

    /* Static Utility methods */ 

    static BeanDefinition groovyScriptFactory(String scriptLocation) { 
     def bd = BeanDefinitionBuilder.genericBeanDefinition(GroovyScriptFactory) 
       .addConstructorArgValue(scriptLocation) 
       .getBeanDefinition() 
     bd.setAttribute(ScriptFactoryPostProcessor.REFRESH_CHECK_DELAY_ATTRIBUTE, 1000) 
     bd 
    } 

} 

initialisieren Anwendung.groovy

@SpringBootApplication 
public class Application { 

    public static void main(String[] args) { 
     SpringApplication app = new SpringApplication(Application) 
     app.addListeners(new AddBeanDefinitionsListener([ 
       'foobar0': groovyScriptFactory("file:/some/path/Foobar0Service.groovy"), 
       'foobar1': groovyScriptFactory("file:/some/path/Foobar1Service.groovy") 
     ])) 
     app.run(args) 
    } 

    @Bean 
    ScriptFactoryPostProcessor scriptFactory() { 
     new ScriptFactoryPostProcessor() 
    } 

} 

(Könnte schöner, wenn mit Spring 4.2's events umgesetzt?)

Verwandte Themen