Gibt es eine Möglichkeit, eine Kopie des ApplicationContext in einer Spring-Anwendung statisch / global anzufordern?
Angenommen, die Hauptklasse startet und initialisiert den Anwendungskontext. Muss sie diesen über den Aufrufstapel an alle Klassen weitergeben, die ihn benötigen, oder gibt es eine Möglichkeit für eine Klasse, nach dem zuvor erstellten Kontext zu fragen? (Was ich nehme an, muss ein Singleton sein?)
quelle
instance()
Methode als Factory zu verwenden. Ich denke jedoch, ich lasse nur den gesamten Code außerhalb des Containers zuerst auf den Container zugreifen. Dann könnte dieser Code Objekte vom Container anfordern.Sie können implementieren
ApplicationContextAware
oder einfach verwenden@Autowired
:SpringBean
wirdApplicationContext
injiziert haben, innerhalb dessen diese Bohne instanziiert wird. Zum Beispiel, wenn Sie eine Webanwendung mit einer ziemlich normalen Kontexthierarchie haben:und
SpringBean
wird im Hauptkontext deklariert, es wird Hauptkontext injiziert; Andernfalls wird, wenn es im MVC-Kontext deklariert ist, der MVC-Kontext eingefügt.quelle
@Inject
zuHier ist ein guter Weg (nicht meiner, die ursprüngliche Referenz ist hier: http://sujitpal.blogspot.com/2007/03/accessing-spring-beans-from-legacy-code.html
Ich habe diesen Ansatz verwendet und es funktioniert gut. Grundsätzlich handelt es sich um eine einfache Bean, die einen (statischen) Verweis auf den Anwendungskontext enthält. Durch Referenzieren in der Frühlingskonfiguration wird es initialisiert.
Schauen Sie sich den Original-Ref an, es ist sehr klar.
quelle
getBean
von Code aus aufrufen , der während eines Unit-Tests ausgeführt wird, da der Spring-Kontext nicht eingerichtet wird, bevor Sie danach fragen. Es ist eine Rennbedingung, in die ich heute nach 2 Jahren erfolgreicher Anwendung dieses Ansatzes geraten bin.Ich glaube, Sie könnten SingletonBeanFactoryLocator verwenden . Die Datei beanRefFactory.xml würde den tatsächlichen applicationContext enthalten. Es würde ungefähr so aussehen:
Und der Code, um eine Bean aus dem Anwendungskontext zu erhalten, von wo auch immer so etwas wäre:
Das Spring-Team rät von der Verwendung dieser Klasse und von Yadayada ab, aber es hat mir gut gepasst, wo ich es verwendet habe.
quelle
Bevor Sie einen der anderen Vorschläge umsetzen, stellen Sie sich diese Fragen ...
Die Antworten auf diese Fragen sind in bestimmten Arten von Anwendungen (z. B. Webanwendungen) einfacher als in anderen, aber es lohnt sich trotzdem, sie zu stellen.
Der Zugriff auf den ApplicationContext verstößt zwar gegen das gesamte Prinzip der Abhängigkeitsinjektion, aber manchmal haben Sie nicht viel Auswahl.
quelle
Wenn Sie eine Web-App verwenden, gibt es auch eine andere Möglichkeit, auf den Anwendungskontext zuzugreifen, ohne Singletons zu verwenden, indem Sie einen Servletfilter und einen ThreadLocal verwenden. Im Filter können Sie mit WebApplicationContextUtils auf den Anwendungskontext zugreifen und entweder den Anwendungskontext oder die erforderlichen Beans im TheadLocal speichern.
Achtung: Wenn Sie vergessen, ThreadLocal zu deaktivieren, treten beim Versuch, die Bereitstellung aufzuheben, böse Probleme auf! Daher sollten Sie es festlegen und sofort einen Versuch starten, der das ThreadLocal im Endteil deaktiviert.
Dies verwendet natürlich immer noch einen Singleton: den ThreadLocal. Aber die eigentlichen Bohnen müssen nicht mehr sein. Das kann sogar anforderungsbezogen sein, und diese Lösung funktioniert auch, wenn Sie mehrere WARs in einer Anwendung mit den Bibliotheken in der EAR haben. Dennoch können Sie diese Verwendung von ThreadLocal als genauso schlecht betrachten wie die Verwendung von einfachen Singletons. ;-);
Vielleicht bietet Spring bereits eine ähnliche Lösung? Ich habe keinen gefunden, aber ich weiß es nicht genau.
quelle
Quelle: http://sujitpal.blogspot.de/2007/03/accessing-spring-beans-from-legacy-code.html
quelle
Schauen Sie sich ContextSingletonBeanFactoryLocator an . Es bietet statische Accessoren, um die Kontexte von Spring abzurufen, sofern sie auf bestimmte Weise registriert wurden.
Es ist nicht schön und komplexer als Sie vielleicht möchten, aber es funktioniert.
quelle
Es gibt viele Möglichkeiten, den Anwendungskontext in der Spring-Anwendung abzurufen. Diese sind unten angegeben:
Über ApplicationContextAware :
Hier erhalten
setApplicationContext(ApplicationContext applicationContext)
Sie den applicationContextÜber Autowired :
Hier
@Autowired
liefert das Schlüsselwort den applicationContext. Autowired hat ein Problem. Dies führt zu Problemen beim Testen von Einheiten.quelle
Beachten Sie, dass Sie Ihre Tests instabil und unvorhersehbar machen, wenn Sie Spring-Test verwenden , indem Sie einen beliebigen Status aus dem aktuellen
ApplicationContext
oder demApplicationContext
selbst in einer statischen Variablen speichern - beispielsweise mithilfe des Singleton-Musters. Dies liegt daran, dass Spring-Test Anwendungskontexte in derselben JVM zwischenspeichert und wiederverwendet. Beispielsweise:@ContextConfiguration({"classpath:foo.xml"})
.@ContextConfiguration({"classpath:foo.xml", "classpath:bar.xml})
@ContextConfiguration({"classpath:foo.xml"})
Wenn Test A ausgeführt wird, wird ein
ApplicationContext
erstellt, und alle Beans, die implementiertApplicationContextAware
oder automatisch verdrahtet werdenApplicationContext
, können in die statische Variable schreiben.Wenn Test B ausgeführt wird, passiert dasselbe, und die statische Variable zeigt jetzt auf Test B.
ApplicationContext
Wenn Test C ausgeführt wird, werden keine Beans erstellt, da die
TestContext
(und hier dieApplicationContext
) aus Test A wiederverwendet werden. Jetzt haben Sie eine statische Variable, die auf eine andereApplicationContext
als die zeigt, die derzeit die Beans für Ihren Test enthält.quelle
Sie sind sich nicht sicher, wie nützlich dies sein wird, aber Sie können den Kontext auch beim Initialisieren der App abrufen. Dies ist der früheste Zeitpunkt, an dem Sie den Kontext abrufen können, noch bevor ein
@Autowire
.quelle
Bitte beachte, dass; Der folgende Code erstellt einen neuen Anwendungskontext, anstatt den bereits geladenen zu verwenden.
Beachten Sie auch, dass
beans.xml
dies Teil dersrc/main/resources
Mittel im Krieg sein sollte, zu denen es gehörtWEB_INF/classes
, wo die eigentliche Anwendung durch das unterapplicationContext.xml
erwähnte geladen wirdWeb.xml
.Es ist schwierig , den
applicationContext.xml
Pfad imClassPathXmlApplicationContext
Konstruktor zu erwähnen .ClassPathXmlApplicationContext("META-INF/spring/applicationContext.xml")
kann die Datei nicht finden.Daher ist es besser, vorhandenen applicationContext mithilfe von Anmerkungen zu verwenden.
quelle
Ich weiß, dass diese Frage beantwortet wurde, aber ich möchte den Kotlin-Code teilen, den ich zum Abrufen des Spring-Kontexts verwendet habe.
Ich bin kein Spezialist, daher bin ich offen für Kritiker, Bewertungen und Ratschläge:
https://gist.github.com/edpichler/9e22309a86b97dbd4cb1ffe011aa69dd
Jetzt ist ein Spring-Kontext öffentlich verfügbar, der dieselbe kontextunabhängige Methode (Junit-Tests, Beans, manuell instanziierte Klassen) wie in diesem Java-Servlet aufrufen kann:
quelle
Führen Sie die automatische Verdrahtung in Spring Bean wie folgt aus: @Autowired private ApplicationContext appContext;
Sie werden das applicationcontext-Objekt.
quelle
Ansatz 1: Sie können ApplicationContext einfügen, indem Sie die ApplicationContextAware-Schnittstelle implementieren. Referenz Link .
Ansatz 2: Autowire-Anwendungskontext in einer der im Frühjahr verwalteten Beans.
Referenz Link .
quelle