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
[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
@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. –
Scheint, dass es refreshable Beans von Groovy-Skripten produziert: https://gist.github.com/thomasdarimont/f7f2ef6f4900b9f89d58 – cybersoft