2011-10-07 11 views
5

Ho un'applicazione java a molla con alcuni componenti utili. Come parte del sistema ho uno script groovy, per elaborare alcuni report. Mi piacerebbe chiamare un componente di primavera da script groovy. Quando sto scrivendo in Java, ho bisogno di usare @Autowired annotazioni all'interno del @Component, vale a direChiamare il componente Spring da groove

@Component 
class Reporter{ 
@Autowired 
SearchService searchService; 

void report(){ 
searchService.search(...); 
... 
} 
} 

Come posso fare lo stesso dal groove? Inizialmente, come posso definire @Component per l'intero script? Il seguente codice:

@Component class Holder{ 
    @Autowired 
    SearchService searchService; 

    def run(){ 
     searchService.search("test"); 
    } 
} 

new Holder().run() 

fallisce con NPE su searchService. Sto eseguendo groovyscripts con GroovyClassloader instatiaded da Java, se è importante. Grazie mille in anticipo!

+0

Come viene creato il contesto dell'applicazione molla? – gkamal

risposta

4

Se si utilizza @Component, è necessario creare contesto primavera come:

def ctx = new GenericApplicationContext() 
new ClassPathBeanDefinitionScanner(ctx).scan('') // scan root package for components 
ctx.refresh() 

o in XML:

<context:component-scan base-package="org.example"/> 

Il codice dovrebbe funzionare se il contesto è stato creato come sopra. Ecco un esempio da Groovy Codehaus

import org.springframework.beans.factory.annotation.Autowired 
import org.springframework.stereotype.Component 

@Component class CalcImpl3 { 
    @Autowired private AdderImpl adder 
    def doAdd(x, y) { adder.add(x, y) } 
} 
+0

grazie mille, è esattamente quello di cui avevo bisogno. A proposito, ho notato che ci vuole del tempo per creare e aggiornare il contesto. Probabilmente sarebbe meglio passare il contesto primaverile come parametro per il groovy script, vero? – tmp120210

+0

puoi provarlo, ma il contesto deve ancora essere aggiornato (ad es.per '@ Autowired' per lavorare + altre cose) – tolitius

+0

Grazie per questa risposta, la più utile sul web al momento: D comunque, dopo aver annotato la mia classe Groovy con Component e inserendo le 3 linee sul contesto nel mio costruttore, non posso ancora Autowire un servizio che ho nel mio progetto di primavera. Mi sta dicendo che sembra mancare la configurazione (liquibase config) ma ho il mio file application.yml bello e snello :( – Alex

1

tre possibilità:

  1. Se il codice Groovy può essere pre-compilato e incluso nel classpath allora sarà creato e iniettata come qualsiasi altro fagiolo sarebbe durante <context:component-scan>. Sembra che questo potrebbe non essere il caso dato che stai usando GroovyClassLoader.

  2. Utilizzare la primavera Dynamic Language Support e utilizzare <lang:groovy> per creare il bean invece di utilizzare GroovyClassLoader. Quindi utilizzare <lang:property> per iniettare le proprietà anziché utilizzare @Autowired.

  3. Se è ancora necessario utilizzare GroovyClassLoader, è possibile chiedere al bean di essere iniettato utilizzando AutowiredAnnotationBeanPostProcessor.

Per esempio, se obj è un riferimento all'oggetto creato da GroovyClassLoader:

AutowiredAnnotationBeanPostProcessor aabpp = 
    (AutowiredAnnotationBeanPostProcessor)applicationContext. 
     getBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME); 

aabpp.processInjection(obj); 

C'è una quarta possibilità anche, ma non sono sicuro se funziona con GroovyClassLoader, vale a utilizzare Load-time Weaving.

+0

Grazie mille per la risposta. Per quanto ho capito, la tua risposta è utile quando abbiamo bisogno di implementare un bean in groovy, giusto? Per ora, voglio solo chiamare il componente esistente dallo script groovy, quindi non è utile per me in questo momento, ma salverò la tua risposta per riferimenti futuri. – tmp120210