2015-08-25 6 views
7

Ich mag würde Dynamic Languages Support von Spring Framework verwenden, eine aufladbare Bohne (zur Laufzeit!) von einem Groovy Skript zu erstellen. Ich möchte vermeiden, xml Konfiguration, und verwenden Sie Anmerkungen (oder ähnliches) innerhalb einer Spring Boot Application Kontext.mit Spring Dynamic Languages ​​Unterstützung von Groovy Konfiguration

Dies ist eine Erweiterung auf eine question that's already been asked, die Erweiterung ist, dass ich will, um meine Hände schmutzig mit BeanPostProcessors, Handlers, Parsers, whatever it takes zu bekommen.

Ich habe mir die javadoc für ScriptFactoryPostProcessor kurz angesehen und habe Arbeitsbeispiele entwickelt. Ich möchte wissen, warum Application.groovy (v2) nicht funktioniert?


beans.xml - funktioniert! (Aber ich will die Bohnen definieren, in Application.groovy statt xml ...)

<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor"> 
    <property name="defaultRefreshCheckDelay" value="1000" /> 
</bean> 

<bean id="foobar0" class="org.springframework.scripting.groovy.GroovyScriptFactory"> 
    <constructor-arg value="file:/C:/someDir/src/main/static/FoobarService.groovy"/> 
</bean> 

Application.groovy (v1) - funktioniert! (Aber ist eine sehr hässliche Abhilfe)

@SpringBootApplication 
public class Application { 
    public static void main(String[] args) { 
     SpringApplication app = new SpringApplication(Application) 
     // Add GroovyScriptFactory after Application is prepared... 
     app.addListeners(new ApplicationListener<ApplicationPreparedEvent>() { 
      void onApplicationEvent(ApplicationPreparedEvent event) { 
       def registry = (BeanDefinitionRegistry) event.applicationContext.autowireCapableBeanFactory 
       def bd = BeanDefinitionBuilder.genericBeanDefinition(GroovyScriptFactory) 
         .addConstructorArgValue("file:/C:/someDir/src/main/static/FoobarService.groovy") 
         .getBeanDefinition() 
       bd.setAttribute(ScriptFactoryPostProcessor.REFRESH_CHECK_DELAY_ATTRIBUTE, 1000) 
       registry.registerBeanDefinition('foobar0', bd) 
      } 
     }) 
     app.run(args) 
    } 
    @Bean 
    ScriptFactoryPostProcessor scriptFactory() { 
     new ScriptFactoryPostProcessor() 
    } 
} 

Application.groovy (v2) - funktioniert nicht - warum nicht?

@SpringBootApplication 
public class Application { 
    public static void main(String[] args) { 
     SpringApplication.run(Application, args) 
    } 
    @Bean 
    ScriptFactoryPostProcessor scriptFactory() { 
     new ScriptFactoryPostProcessor() 
    } 
    @Bean 
    GroovyScriptFactory foobar0() { 
     new GroovyScriptFactory("file:/C:/someDir/src/main/static/FoobarService.groovy") 
    } 
} 

Es sieht aus wie es etwas mit dem zu tun ist, wie/wann die Bohnen Definitionen initialisiert werden im Lebenszyklus eines Application. Ich habe versucht, mit @Order und @DependsOn Bohnen Bestellung zu steuern - ohne Erfolg. Erwähnenswert ist, dass ich jetzt das folgende Protokoll wiederhole - was aussieht, als ob die ScriptFactoryPostProcessor die Bean ständig mit einer "Null" -Bohnedefinition überschreibt (warum?).

2015-08-27 12:04:11.312 INFO 5780 --- [   main] o.s.b.f.s.DefaultListableBeanFactory  : 
Overriding bean definition for bean 'scriptFactory.foobar0': replacing [Generic bean: class [null]; 
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; p 
rimary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=n 
ull] with [Generic bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=0; depen 
dencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; i 
nitMethodName=null; destroyMethodName=null] 

Verwandte:

  • SPR-10253 - Erfrischende kommentierte Groovy-Controller verursachen Classcast
  • SPR-10689 - tag in Version 2.5 und höher für aktualisierbare Spring MVC nicht Endpunkte
  • SPR-12300 funktioniert - Unterstützung für dynamische Sprachen hinzufügen aktualisierbare Bohnen in @Configuration Klassen
+0

[Die Frage, die Sie verknüpft] (http: // Stackoverflow. com/q/26208020/880772) enthält ein Beispiel mit Java-Konfiguration. Hat das für dich funktioniert? Warum nicht 'RefreshableResourceScriptSource' verwenden? – approxiblue

+0

@approxiblue - es ist ein gutes Beispiel, aber es erfordert eine Wrapper-Bean-Klasse (d. H. 'Calculator'), um den zugrundeliegenden' ScriptEvaluator' dynamisch aufzurufen. Was passiert, wenn ich eine neue Funktion "subtrahieren" hinzufügen möchte? Muss ich eine neue Methode zu 'Calculator' hinzufügen und die Klasse manuell neu kompilieren? Nicht sehr dynamisch. Idealerweise möchte ich ein Groovy-Skript/eine Klasse, deren Änderungen zur Laufzeit von Spring erkannt und aktualisiert werden können. Spring ist selbst eine Spring-Bean (und die damit verbundene Magier-Magie). Stellen Sie sich einen '@ RestController' vor, den Sie dynamisch zur Laufzeit aktualisieren und hinzufügen können. –

+0

Scheint, dass es refreshable Beans von Groovy-Skripten produziert: https://gist.github.com/thomasdarimont/f7f2ef6f4900b9f89d58 – cybersoft

Antwort

0

Einfachere Alternativen:

  • Put FooBarService auf dem Classpath und mit Anmerkungen versehen es mit @Component

oder

  • die lang Namespace in mybeans.xml verwenden

-

<lang:groovy id="foobarService" 
    script-source="file:src/main/static/FoobarService.groovy" /> 

Application.groovy

@SpringBootApplication 
@ImportResource("classpath:mybeans.xml") 
public class Application { 
    public static void main(String[] args) { 
     SpringApplication.run(Application, args) 
    } 
} 
+2

Danke für die Alternativen @ slim-l, aber leider sind beide Ihre Lösungen nicht meine Frage (sie aren ' t ** nachladbar **, außer ich täusche mich). Ihre erste Alternative verwendet nicht [DLS] (http://docs.spring.io/spring/docs/current/spring-framework-reference/html/dynamic-language.html). Ihre zweite Alternative fehlt das 'refresh-check-delay =" 1000 "Attribut und verwendet auch' xml', das ich vermeiden wollte. –

Verwandte Themen