Spring-Initialisierungsreihenfolge

Angenommen, ich habe ein paar Frühlingsbohnen:


   
   

"B" macht einen Remote-Dienst verfügbar, der kein "A" benötigt. Angenommen, "A" benötigt eine nicht vernachlässigbare Zeit zum Laden. Dies bedeutet, dass die Anwendung während eines Neustartzyklus den Remote-Client aufhängt, der sich tatsächlich mit dem Server verbinden kann, aber auf eine Antwort wartet, bis der Spring-Container vollständig initialisiert ist.

Was ich gerne tun könnte, ist, dass der Remote-Dienst "B" sofort reagiert, selbst wenn (je nach Anwendungsstatus) NOT_READY oder ähnliches zurückgegeben werden kann. Der Container erzwingt jedoch eine Wartezeit, bis alle Beans initialisiert sind, selbst wenn Sie die Beans als Lazy-Init und unabhängig von der Ladereihenfolge angeben.

Ich vermute, dass die sofortige Verfügbarkeit von "B" bedeuten würde, dass die Feder einen teilweise initialisierten Container zur Verfügung stellen müsste, was sich schlecht anhört. Wie auch immer, ich würde mich über jede Information freuen, die jemand über die Initialisierungsreihenfolge hat und ob Sie vernünftige Problemumgehungen gefunden haben.

2
Könnten Sie näher erläutern, warum Bean A eine "nicht zu vernachlässigende Zeit" benötigt, um sich selbst zu instantiieren? Gibt es eine mögliche Antwort, die Bean A neu faktorisiert, so dass die nicht vernachlässigbare Zeit zu einer Funktion wird, die außerhalb des Instanziierungsprozesses aufgerufen wird?
hinzugefügt der Autor David Harrison, Quelle

2 Antworten

Beziehe dich nicht direkt auf "A". Beziehe dich stattdessen auf eine Bohne, die eine FABRIK für Bohnen "A" ist; Auf diese Weise kann die Factory-Bean erstellt werden, ohne den Initialisierungstreffer für die Instanziierung von "A" zu übernehmen. Du musst deine Klassen umgestalten, die sich auf ein "A" beziehen, um natürlich zuerst ein "A" zu erhalten.

Oder Sie könnten eine Bean "AA" erstellen, die ein Container für Bean "A" ist, die einen Initialisierungsstatus hat und die Schnittstelle von Bean "A" freilegt; Nach dem Aufruf setzt es seinen Initialisierungszustand auf nicht initialisiert und beginnt die Initialisierung von Bean "A" in einem Thread; Aufrufe an beliebige Schnittstellenmethoden von "A" an "AA" können dann eine nicht bereit Antwort blockieren oder zurückgeben, bis die Initialisierung von "A" innerhalb von "AA" abgeschlossen ist.

Das hängt alles davon ab, was Ihre Definition von "benötigt eine nicht zu vernachlässigende Zeit zu laden" ist. Warum braucht es eine nicht zu vernachlässigende Zeit zu laden? Gibt es eine besonders schwierige Initialisierung, die in A vor sich geht? Oder ist A einfach so ungeheuer riesig, dass es die JVM erstickt?

3
hinzugefügt

Ich verstehe nicht, warum "A eine nicht vernachlässigbare Zeit zum Laden benötigt", aber vielleicht könnten Sie sich durch Refactoring A initialisieren. Verwenden Sie InitializingBean nicht und behandeln Sie kein ApplicationEvent. Initialisieren Sie einfach die erste Anfrage, die bearbeitet werden soll. Dies wird die erste Anfrage verlangsamen!

Die andere Möglichkeit besteht darin, die Initialisierung in einen getrennten Thread zu verschieben, der von der Bean erstellt wurde, die ein ApplicationEvent verarbeitet. Der Thread ruft die Initialisierungsmethode der Bean asynchron auf. Seien Sie vorsichtig mit Anfragen an die nicht initialisierte Bean!

0
hinzugefügt
Während A geladen wird, hängen Anrufer bis zum Timeout, da sie einen Socket öffnen können, aber warten, bis die Serverinitialisierung abgeschlossen ist. Sie möchten den Dienst manuell laden, um sofort zu antworten. Ich hatte gehofft, die chaotische Alternative der Initialisierung in einem manuell gestarteten Hintergrundthread zu vermeiden.
hinzugefügt der Autor Steve B., Quelle