2012-04-02 6 views
6

Spring hat den schönen Mechanismus PropertyPlaceholderConfigurer für das Injizieren von Werten wie Timeouts, JDBC Urls und so weiter in Spring Beans für Konfigurationszwecke. Gibt es eine vernünftige Möglichkeit, Konfigurationswerte zu handhaben, die sich zur Laufzeit ändern können?Spring: wie transparente Laufzeitkonfiguration der veränderbaren Eigenschaft zu tun

UPDATE: Mit Spring 3.1 gibt es eine gute Möglichkeit, nicht statische Konfigurationsquellen wie die Datenbank über PropertySource s einzubinden. Einige ApplicationContexte stellen einen Refresh-Mechanismus bereit, der prinzipiell in der Lage ist, Konfigurationswerte zu ändern. Es stoppt jedoch zuerst die Anwendung, erstellt dann alle Beans neu und startet dann den Anwendungskontext erneut. Für unsere Zwecke würde ich jedoch einen Weg brauchen, dies transparent zu machen, so dass der Server aktuell laufende Anfragen korrekt behandelt.

Eine andere Idee, dies zu tun, wäre ein benutzerdefinierter Bereich, der neue Objekte erstellt, wenn sich die Konfiguration ändert. Leider verwendet die dem Scope zur Verfügung gestellte ObjectFactory eine vorverarbeitete Bean-Definition, so dass die Platzhalter nicht neu aus der Konfiguration gelesen werden. Somit haben die erstellten Objekte die gleiche Konfiguration. :-(

+0

Wahrscheinlich wäre es ein PropertyOverrideConfigurer http://StackOverflow.com/a/595201/21499, aber ich denke, der Property Override-Mechanismus ist ziemlich umständlich zu verwenden und fehleranfällig. –

Antwort

2

Das Folgende ist ein bisschen seltsam, aber funktioniert. Sie erstellen einen custom scope mit dem Namen reconfigurable, der alle in diesem Bereich erstellten Beans bei jeder Konfigurationsaktualisierung wegwirft. Daher wird nach einer Konfigurationsänderung eine neue Bean erstellt.

Die tatsächlichen Konfigurationswerte müssen über die Federausdrucksprache abgerufen werden, da die Werte für die normale $ {} -Syntax und PropertyOverrideConfigurer in der BeanDefinition dauerhaft zu fixieren scheinen. Eine Bohne Deklaration für eine Bohne mit einem rekonfigurierbaren Eigenschaft sieht someProperty wie folgt aus:

<bean class="blablu.Testbean" scope="reconfigurable" 
    p:someProperty="#{ config['configexplicit']}"> 
    <aop:scoped-proxy /> 
</bean> 

Sie müssen AOP verwenden: scoped-Proxy, so dass Bohnen, die diese Bohne immer die frischesten konfiguriert Bean aus dem benutzerdefinierten Bereich abrufen .

Das Deklarieren von Eigenschaften mit @Value funktioniert auch; wenn Sie Komponente Scan verwenden müssen Sie den Umfang mit der Anmerkung

@Scope(value="reconfigurableScope", proxyMode=ScopedProxyMode.TARGET_CLASS) 

erklären Wenn Sie Details kümmern: die Grundidee des Anwendungsbereichs ist:

public class ReconfigurableScope implements Scope { 

    private final Map<String, Object> nameToObjectMap = new ConcurrentHashMap<String, Object>(); 

    public Object get(final String name, final ObjectFactory<?> objectFactory) { 
     Object bean = nameToObjectMap.get(name); 
     if (null == bean) { 
      bean = objectFactory.getObject(); 
      nameToObjectMap.put(name, bean); 
     } 
     return bean; 
    } 

    // called from outside on each configuration change 
    public void update(final ConfigurationObservable observable, final Object arg) { 
     nameToObjectMap.clear(); 
    } 

} 

plus einige Thread-Sicherheit und Reinigung Material: Die entfernten Beans müssen etwas später und im Anwendungskontext geschlossen werden.

+0

Jedes Quellcode-Beispiel Ihres benutzerdefinierten Bereichs ist möglich? :) – Kakawait

2

Leider Konfiguration von properties Dateien ist statisch und beim Start passiert, was ich normalerweise tue dynamische Attribute über aussetzt. Um

<context:mbean-export/> 

:

@ManagedResource 
@Service 
public class BusinessService { 

    @ManagedAttribute 
    private int age; 

    public int getAge() { 
     return age; 
    } 

    public void setAge(int age) { 
     this.age = age; 
    } 

    public void businessMethod() { 
     //use age... 
    } 

} 

hinzufügen Speichern Ihre Konfiguration Nun können Sie über jconsole oder einen anderen JMX-Client auf dieses Attribut zugreifen und dieses ändern (siehe auch: 23.3.2 Using Source-Level Metadata (JDK 5.0 annotations).

+0

Eigenschaftsdateien sind nicht unbedingt statisch - sie können sich irgendwo im Dateisystem befinden und von ops geändert werden. Sie haben Recht: Man kann andere Mechanismen verwenden, um Konfigurationswerte zu aktualisieren, aber ich möchte den schönen Spring-Platzhaltermechanismus verwenden. Sonst - wie würdest du zB ein Timeout für ein WebserviceTemplate ohne viel Klebercode aktualisieren? –

+0

@hstoerr: wrt 'WebserviceTemplate' - es erfordert etwas Klebstoff-Code, auch wenn Sie nichts aktualisieren müssen: http://onebyteatatime.wordpress.com/2009/03/19/how-to-set-socket-timeout -using-spring-webservicetemplate/und http://stackoverflow.com/questions/6733744 –

0

Für eine effektive Rekonfiguration der Laufzeit können Sie das Cloud Config-Projekt von spring verwenden. In dieser Anordnung hätten Sie ein , sagen wir ein Git-Repository, das Ihre Konfigurationswerte enthält. Dann legen Sie eine Configuration Server vor diesem Repository. Dieser Server wird aktualisiert, sobald ein Push-Vorgang für das Sicherungs-Repository ausgeführt wird.Schließlich sind Ihre Apps Clients dieser Config Server und ziehen die neuen Konfigurationen daraus. Überprüfen Sie Spring Cloud für weitere Details.

1

Es ist ein laufendes Beispiel dafür, was Sie versuchen, hier zu erreichen: https://github.com/ldojo/spring-cloud-config-examples

Es zeigt, wie ein Frühling Wolke Config Server und einem Client-Dienst kann über Frühling Cloud-Bus kommunizieren, und die Konfigurationseigenschaften des Clients ändern zur Laufzeit bei einer Konfigurationsänderung im Repo des Konfig-Servers.

Verwandte Themen