Wir haben den gleichen Anwendungsfall. Wie bereits erwähnt, besteht eines der Hauptprobleme bei der Neuerstellung einer Bean während der Laufzeit darin, die Referenzen zu aktualisieren, die bereits injiziert wurden. Dies ist die größte Herausforderung.
Um dieses Problem zu umgehen, habe ich die AtomicReference-Klasse <> von Java verwendet. Anstatt die Bean direkt zu injizieren, habe ich sie als AtomicReference umschlossen und dann injiziert. Da das von der AtomicReference umschlossene Objekt threadsicher zurückgesetzt werden kann, kann ich das zugrunde liegende Objekt ändern, wenn eine Datenbankänderung erkannt wird. Unten ist ein Beispiel einer Konfiguration/Verwendung dieses Musters:
Ich injiziere dann die Bohne wo erforderlich, z.B.
In einer separaten Klasse ich einen Scheduler-Thread ausführen, der beim Start des Anwendungskontexts gestartet wird. Die Klasse sieht ungefähr so aus:
class Manager implements Runnable {
private ScheduledExecutorService scheduler;
public void start() {
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(this, 0, 120, TimeUnit.SECONDS);
}
public void stop() {
scheduler.shutdownNow();
}
@Override
public void run() {
try {
if (KafkaConfiguration.isRefreshNeeded()) {
AtomicReference<KafkaTemplate<String, String>> kafkaTemplate =
(AtomicReference<KafkaTemplate<String, String>>) Registry.getApplicationContext().getBean("kafkaTemplate");
// Get new instance here. This will have the new value for the server list
// that was "refreshed"
KafkaConfiguration config = new KafkaConfiguration();
// The set here replaces the wrapped objet in a thread safe manner with the new bean
// and thus all injected instances now use the newly created object
kafkaTemplate.set(config.kafkaTemplate().get());
}
} catch (Exception e){
} finally {
}
}
}
ich immer noch auf dem Zaun bin, wenn dies etwas, das ich tun befürworten würde, wie es einen leichten Geruch es hat. Bei eingeschränkter und sorgfältiger Verwendung bietet es jedoch einen alternativen Ansatz für den angegebenen Anwendungsfall. Bitte beachten Sie, dass dieses Codebeispiel den alten Hersteller aus Kafka-Sicht offen lässt. In Wirklichkeit müsste man einen flush() Aufruf an den alten Produzenten machen, um ihn zu schließen. Aber das soll das Beispiel nicht zeigen.
Die Eigenschaften von Beans werden in der BeanFactory Post Processing-Phase geladen, und ich glaube nicht, dass wir in der Lage sind, danach viel zu tun, besonders in Singletons, Sie müssten den App-Kontext wiederherstellen, in den die Beans geladen werden. Hier ein interessantes Beispiel: http://stackoverflow.com/questions/4084890/spring-replacing-the-bean-property-values-with-new-property-file-values – mariubog