Frühling erhält aktuellen ApplicationContext


105

Ich verwende Spring MVC für meine Webanwendung. Meine Bohnen sind in der spring-servlet.xmlDatei " " geschrieben

Jetzt habe ich eine Klasse MyClassund möchte mit Spring Bean auf diese Klasse zugreifen

In der habe spring-servlet.xmlich folgendes geschrieben

<bean id="myClass" class="com.lynas.MyClass" />

Jetzt muss ich mit darauf zugreifen ApplicationContext

ApplicationContext context = ??

Damit ich es tun kann

MyClass myClass = (MyClass) context.getBean("myClass");

Wie macht man das??


3
@Autowired MyClass myClass sollte den Job machen!
Mannekenpix

Antworten:


160

Einfach injizieren ..

@Autowired
private ApplicationContext appContext;

oder implementieren Sie diese Schnittstelle: ApplicationContextAware


Vielleicht kann das funktionieren: stackoverflow.com/questions/11682858/…
gipinani

Die folgende ApplicationContextProvider.javaAntwort scheint die zuverlässigste Lösung dafür zu sein.
Ionut

1
Es wird jedes Mal NULL zurückgegeben. Um hier zu erwähnen, dass ich dies in einer normalen Klasse mache, die weder ein "@RestController" noch eine "@Component" ist
zulkarnain shah

1
Laut Spring-Dokumentation ist es aufgrund einiger Probleme am besten, @Autowired zu vermeiden. Hier ist der Link spring.io/understanding/application-context . Am besten implementieren Sie die ApplicationContextAware-Schnittstelle.
Durja Arai

89

Ich denke, dieser Link zeigt den besten Weg, um Anwendungskontext überall abzurufen, selbst in der Nicht-Bean-Klasse. Ich finde es sehr nützlich. Hoffe es ist das gleiche für dich. Das Folgende ist der abstrakte Code davon

Erstellen Sie eine neue Klasse ApplicationContextProvider.java

package com.java2novice.spring;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class ApplicationContextProvider implements ApplicationContextAware{

    private static ApplicationContext context;

    public static ApplicationContext getApplicationContext() {
        return context;
    }

    @Override
    public void setApplicationContext(ApplicationContext ac)
            throws BeansException {
        context = ac;
    }
}

Fügen Sie einen Eintrag in application-context.xml hinzu

<bean id="applicationContextProvider"
                        class="com.java2novice.spring.ApplicationContextProvider"/>

Im Fall von Anmerkungen (anstelle von application-context.xml)

@Component
public class ApplicationContextProvider implements ApplicationContextAware{
...
}

Holen Sie sich den Kontext so

TestBean tb = ApplicationContextProvider.getApplicationContext().getBean("testBean", TestBean.class);

Prost!!


1
Ich habe ähnlich wie Vivek codiert. Ich vermeide es jedoch, jedes Mal einen neuen ApplicationContextProvider () zu erstellen, wenn ich getBean () aus dem Kontext aufrufen muss. Was ich getan habe, war eine statische ApplicationContextProvider.getApplicationContext() Methode. Wenn es dann Zeit ist, den aktuellen App-Kontext zu benötigen, rufe ich ApplicationContextProvider appContext = ApplicationContextProvider.getApplicationContext()
Folgendes

1
Ja Panini Luncher, das wäre immer noch gut. Gemäß Ihrem Vorschlag werde ich es so ändern. :)
Vivek

4
Add- @ComponentOn ApplicationContextProviderkann Konfiguration inaplication-context.xml
Bluearrow

1
Hinweis: Getter und Kontext-Setter sollten synchronisiert werden. Sie vermeiden viele Kopfschmerzen speziell für Unit- / Integrationstests. In meinem Fall enthielt ein ähnlicher ApplicationContextProvider einen alten Kontext (aus dem vorherigen Integrationstest), der viele knifflige Fehler verursachte.
Oleksandr_DJ

43

Falls Sie über einen HttpServlet auf den Kontext zugreifen müssen, der selbst nicht von Spring instanziiert wird (und daher weder @Autowire noch ApplicationContextAware funktionieren) ...

WebApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());

oder

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

Überlegen Sie sich einige der anderen Antworten, bevor Sie dies tun:

new ClassPathXmlApplicationContext("..."); // are you sure?

... da dies Ihnen nicht den aktuellen Kontext gibt, sondern eine weitere Instanz davon für Sie erstellt. Dies bedeutet, dass 1) ein erheblicher Speicherbereich und 2) Beans nicht zwischen diesen beiden Anwendungskontexten geteilt werden.


SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (this) - hat die Aufgabe für mich in der init () -Methode des Liferay-Portlet-Aktionsfilters erledigt.
Igor Baiborodine

Genial, der processInjectionBasedOnCurrentContext hat alle Aufgaben erledigt, die ich brauchte. Vielen Dank @Jaroslav
Jad B.

ApplicationContextAware funktioniert für mich, wenn es wie in Viveks Lösung mit @Component kommentiert ist (ich initialisiere den Spring-Kontext manuell über die Erweiterung von AbstractContextLoaderInitializer / createRootApplicationContext)
hello_earth

Seien Sie gewarnt ... SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (this); passiert nicht sofort, daher können Sie es beispielsweise nicht als erste Zeile in Ihrem Konstruktor verwenden.
SledgeHammer

31

Wenn Sie eine Klasse implementieren, die nicht von Spring instanziiert wurde, wie z. B. einen JsonDeserializer, können Sie Folgendes verwenden:

WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
MyClass myBean = context.getBean(MyClass.class);

8
Es funktioniert nicht bei mir. Meine Klasse ist außerhalb des Frühlingskontexts. Ich habe versucht, Ihren Code zu verwenden, aber er gibt mir eine Null als Antwort. Ich spreche vonContextLoader.getCurrentWebApplicationContext()
R. Karlus

9

Fügen Sie dies Ihrem Code hinzu

@Autowired
private ApplicationContext _applicationContext;

//Add below line in your calling method
MyClass class = (MyClass) _applicationContext.getBean("myClass");

// Or you can simply use this, put the below code in your controller data member declaration part.
@Autowired
private MyClass myClass;

Dadurch wird myClass einfach in Ihre Anwendung eingefügt


6

basierend auf Viveks Antwort, aber ich denke, das Folgende wäre besser:

@Component("applicationContextProvider")
public class ApplicationContextProvider implements ApplicationContextAware {

    private static class AplicationContextHolder{

        private static final InnerContextResource CONTEXT_PROV = new InnerContextResource();

        private AplicationContextHolder() {
            super();
        }
    }

    private static final class InnerContextResource {

        private ApplicationContext context;

        private InnerContextResource(){
            super();
        }

        private void setContext(ApplicationContext context){
            this.context = context;
        }
    }

    public static ApplicationContext getApplicationContext() {
        return AplicationContextHolder.CONTEXT_PROV.context;
    }

    @Override
    public void setApplicationContext(ApplicationContext ac) {
        AplicationContextHolder.CONTEXT_PROV.setContext(ac);
    }
}

Das Schreiben von einer Instanzmethode in ein statisches Feld ist eine schlechte Praxis und gefährlich, wenn mehrere Instanzen manipuliert werden.


Es gibt eine org.springframework.core.io.ContextResourceSchnittstelle. Ich würde vorschlagen, einen anderen Namen für die innere Klasse zu wählen ContextResource, um Unordnung zu vermeiden.
Alexander Radchenko

@ AlexanderRadchenko Ok, ich habe es in InnerContextResource geändert
Juan

1

Es gibt viele Möglichkeiten, den Anwendungskontext in der Spring-Anwendung abzurufen. Diese sind unten angegeben:

  1. Über ApplicationContextAware :

    import org.springframework.beans.BeansException;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    
    public class AppContextProvider implements ApplicationContextAware {
    
    private ApplicationContext applicationContext;
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
    }

Hier erhalten setApplicationContext(ApplicationContext applicationContext)Sie den applicationContext

  1. Über Autowired :

    @Autowired
    private ApplicationContext applicationContext;

Hier @Autowiredliefert das Schlüsselwort den applicationContext.

Für weitere Informationen besuchen Sie diesen Thread

Vielen Dank :)


0

Eine andere Möglichkeit besteht darin, applicationContext über das Servlet einzufügen.

Dies ist ein Beispiel für das Einfügen von Abhängigkeiten bei Verwendung von Spring-Webdiensten.

<servlet>
        <servlet-name>my-soap-ws</servlet-name>
        <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
        <init-param>
            <param-name>transformWsdlLocations</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:my-applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>5</load-on-startup>

</servlet>

Alternativ können Sie den Anwendungskontext wie unten gezeigt in Ihre web.xml einfügen

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/classes/my-another-applicationContext.xml
        classpath:my-second-context.xml
    </param-value>
</context-param>

Grundsätzlich versuchen Sie, dem Servlet mitzuteilen, dass es nach Beans suchen soll, die in diesen Kontextdateien definiert sind.


0

Schritt 1 : Injizieren Sie den folgenden Code in die Klasse

@Autowired
private ApplicationContext _applicationContext;

Schritt 2 : Schreiben Sie Getter & Setter

Schritt 3 : Definieren Sie autowire = "byType" in der XML-Datei, in der die Bean definiert ist


0

Selbst nach dem Hinzufügen von @Autowire, wenn Ihre Klasse kein RestController oder keine Konfigurationsklasse ist, wurde das applicationContext-Objekt als null angezeigt. Versucht, eine neue Klasse mit unten zu erstellen und es funktioniert gut:

@Component
public class SpringContext implements ApplicationContextAware{

   private static ApplicationContext applicationContext;

   @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws 
     BeansException {
    this.applicationContext=applicationContext;
   }
 }

Sie können dann eine Getter-Methode in derselben Klasse implementieren, die Ihren Anforderungen entspricht, z. B. die Referenz für die implementierte Klasse abrufen durch:

    applicationContext.getBean(String serviceName,Interface.Class)

-11
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-servlet.xml");

Dann können Sie die Bohne abrufen:

MyClass myClass = (MyClass) context.getBean("myClass");

Referenz: springbyexample.org


25
Diese Antwort gibt Ihnen nicht den aktuellen Kontext, sondern erstellt eine andere Instanz.
Jaroslav Záruba
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.