Weitere aktualisierte Antwort auf geskriptete Bean
Ein weiterer Ansatz, der von Spring 2.5.x + unterstützt wird, ist der der Scripted Bean. Sie können eine Vielzahl von Sprachen für Ihr Skript verwenden - BeanShell ist wahrscheinlich die intuitivste, da es dieselbe Syntax wie Java hat, jedoch einige externe Abhängigkeiten erfordert. Die Beispiele sind jedoch in Groovy.
In Abschnitt 24.3.1.2 der Frühjahrsdokumentation wird beschrieben, wie dies konfiguriert wird. Hier sind jedoch einige wichtige Auszüge, die den Ansatz veranschaulichen, den ich bearbeitet habe, um sie für Ihre Situation besser anwendbar zu machen:
<beans>
<!-- This bean is now 'refreshable' due to the presence of the 'refresh-check-delay' attribute -->
<lang:groovy id="messenger"
refresh-check-delay="5000" <!-- switches refreshing on with 5 seconds between checks -->
script-source="classpath:Messenger.groovy">
<lang:property name="message" value="defaultMessage" />
</lang:groovy>
<bean id="service" class="org.example.DefaultService">
<property name="messenger" ref="messenger" />
</bean>
</beans>
Das Groovy-Skript sieht folgendermaßen aus:
package org.example
class GroovyMessenger implements Messenger {
private String message = "anotherProperty";
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message
}
}
Da der Systemadministrator Änderungen vornehmen möchte, können sie (oder Sie) den Inhalt des Skripts entsprechend bearbeiten. Das Skript ist nicht Teil der bereitgestellten Anwendung und kann auf einen bekannten Speicherort verweisen (oder auf einen, der beim Start über einen Standard-PropertyPlaceholderConfigurer konfiguriert wird).
Obwohl im Beispiel eine Groovy-Klasse verwendet wird, kann die Klasse Code ausführen, der eine einfache Eigenschaftendatei liest. Auf diese Weise bearbeiten Sie das Skript nie direkt. Berühren Sie es einfach, um den Zeitstempel zu ändern. Diese Aktion löst dann das Neuladen aus, was wiederum die Aktualisierung von Eigenschaften aus der (aktualisierten) Eigenschaftendatei auslöst, wodurch schließlich die Werte im Spring-Kontext aktualisiert werden und los geht's.
In der Dokumentation wird darauf hingewiesen, dass diese Technik für die Konstruktorinjektion nicht funktioniert, aber vielleicht können Sie das umgehen.
Die Antwort wurde aktualisiert, um dynamische Eigenschaftsänderungen abzudecken
Ein Ansatz aus diesem Artikel , der den vollständigen Quellcode enthält , lautet:
* a factory bean that detects file system changes
* an observer pattern for Properties, so that file system changes can be propagated
* a property placeholder configurer that remembers where which placeholders were used, and updates singleton beans’ properties
* a timer that triggers the regular check for changed files
Das Beobachtermuster wird von den Schnittstellen und Klassen ReloadableProperties, ReloadablePropertiesListener, PropertiesReloadedEvent und ReloadablePropertiesBase implementiert. Keiner von ihnen ist besonders aufregend, nur normaler Umgang mit Hörern. Die Klasse DelegatingProperties dient zum transparenten Austausch der aktuellen Eigenschaften, wenn Eigenschaften aktualisiert werden. Wir aktualisieren nur die gesamte Eigenschaftskarte auf einmal, damit die Anwendung inkonsistente Zwischenzustände vermeiden kann (dazu später mehr).
Jetzt kann die ReloadablePropertiesFactoryBean geschrieben werden, um eine ReloadableProperties-Instanz zu erstellen (anstelle einer Properties-Instanz, wie dies bei der PropertiesFactoryBean der Fall ist). Wenn der RPFB dazu aufgefordert wird, überprüft er die Änderungszeiten der Dateien und aktualisiert bei Bedarf seine ReloadableProperties. Dies löst die Beobachtermustermaschinerie aus.
In unserem Fall ist der einzige Listener der ReloadingPropertyPlaceholderConfigurer. Es verhält sich wie ein PropertyPlaceholderConfigurer für Standardfedern, mit der Ausnahme, dass alle Verwendungen von Platzhaltern verfolgt werden. Wenn nun Eigenschaften neu geladen werden, werden alle Verwendungen jeder geänderten Eigenschaft gefunden und die Eigenschaften dieser Singleton-Beans erneut zugewiesen.
Die ursprüngliche Antwort unten bezieht sich auf statische Eigenschaftsänderungen:
Klingt so, als ob Sie nur externe Eigenschaften in Ihren Spring-Kontext einfügen möchten. Das PropertyPlaceholderConfigurerist für diesen Zweck ausgelegt:
<!-- Property configuration (if required) -->
<bean id="serverProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<!-- Identical properties in later files overwrite earlier ones in this list -->
<value>file:/some/admin/location/application.properties</value>
</list>
</property>
</bean>
Anschließend verweisen Sie mit Platzhaltern für die Ant-Syntax auf die externen Eigenschaften (die verschachtelt werden können, wenn Sie dies ab Spring 2.5.5 möchten).
<bean id="example" class="org.example.DataSource">
<property name="password" value="${password}"/>
</bean>
Anschließend stellen Sie sicher, dass auf die Datei application.properties nur der Administrator und der Benutzer zugreifen können, der die Anwendung ausführt.
Beispiel application.properties:
Passwort = Erdferkel
configurationBean muss also zur Laufzeit aktualisiert werden - oder jedes Mal, wenn der Administrator die Werte ändert? Ich das deine Frage? Oder möchten Sie, dass dieDataSource/MailSenderBeans zur Laufzeit die aktualisierte Konfiguration verwenden? Oder ist es beides?