Spring ottiene ApplicationContext corrente


105

Sto usando Spring MVC per la mia applicazione web. I miei fagioli sono scritti in " spring-servlet.xml" file

Ora ho una classe MyClasse voglio accedere a questa classe utilizzando Spring Bean

In spring-servlet.xmlho scritto di seguito

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

Ora ho bisogno di accedere a questo utilizzando ApplicationContext

ApplicationContext context = ??

Così posso farlo

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

Come fare questo??


3
@Autowired MyClass myClass dovrebbe fare il lavoro!
Mannekenpix

Risposte:


161

Iniettalo semplicemente ..

@Autowired
private ApplicationContext appContext;

o implementare questa interfaccia: ApplicationContextAware


Forse questo può funzionare: stackoverflow.com/questions/11682858/...
gipinani

La seguente ApplicationContextProvider.javarisposta sembra essere la soluzione più affidabile per questo.
Ionut

1
Restituisce NULL ogni volta. Per menzionare qui che lo sto facendo all'interno di una classe normale che non è né un "@RestController" né un "@Component"
zulkarnain shah

1
Secondo la documentazione di Spring, è meglio evitare @Autowired a causa di alcuni problemi. Ecco il link spring.io/understanding/application-context . L'opzione migliore è implementare l'interfaccia ApplicationContextAware.
Durja Arai

89

Penso che questo collegamento dimostri il modo migliore per ottenere il contesto dell'applicazione ovunque, anche nella classe non bean. Lo trovo molto utile. Spero sia lo stesso per te. Di seguito è riportato il codice astratto di esso

Crea una nuova classe 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;
    }
}

Aggiungi una voce in application-context.xml

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

Nel caso delle annotazioni (invece di application-context.xml)

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

Ottieni il contesto in questo modo

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

Saluti!!


1
Ho codificato in modo simile a Vivek. Ma evito di creare un nuovo ApplicationContextProvider () ogni volta che devo chiamare getBean () dal contesto. Quello che ho fatto è stato avere un ApplicationContextProvider.getApplicationContext() metodo statico . Quindi, quando è il momento di aver bisogno del contesto dell'app corrente, invoco:ApplicationContextProvider appContext = ApplicationContextProvider.getApplicationContext()
Panini Luncher

1
Sì Panini Luncher, sarebbe comunque buono. Secondo il tuo suggerimento lo cambierò in questo modo. :)
Vivek

4
Aggiungi @Componentsu ApplicationContextProviderconfigurazione può evitare inaplication-context.xml
BlueArrow

1
Nota: getter e setter del contesto dovrebbero essere sincronizzati. Eviterai un sacco di mal di testa specialmente per i test di unità / integrazione. Nel mio caso ApplicationContextProvider simile conteneva un vecchio contesto (dal precedente test di integrazione) che causava molti bug complicati.
Oleksandr_DJ

43

Nel caso in cui sia necessario accedere al contesto dall'interno di un HttpServlet che a sua volta non è istanziato da Spring (e quindi né @Autowire né ApplicationContextAware funzioneranno) ...

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

o

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

Per quanto riguarda alcune delle altre risposte, pensaci due volte prima di farlo:

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

... poiché questo non ti dà il contesto corrente, piuttosto ne crea un'altra istanza per te. Ciò significa che 1) una porzione significativa di memoria e 2) i bean non sono condivisi tra questi due contesti applicativi.


SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (this) - ha svolto il lavoro per me nel metodo init () del filtro di azione del portlet di Liferay.
Igor Baiborodine

Fantastico, processInjectionBasedOnCurrentContext ha fatto tutto il lavoro di cui avevo bisogno. Molte grazie @Jaroslav
Jad B.

ApplicationContextAware funziona per me, quando è annotato con @Component come nella soluzione di Vivek (sto inizializzando manualmente il contesto Spring tramite l'estensione AbstractContextLoaderInitializer / createRootApplicationContext)
ciao_earth

Attenzione ... SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (this); non accade immediatamente, quindi non puoi usarlo come prima riga nel tuo costruttore, ad esempio.
SledgeHammer

31

Se stai implementando una classe che non è istanziata da Spring, come un JsonDeserializer puoi usare:

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

8
Non funziona per me. La mia classe è fuori dal contesto primaverile. Ho provato a usare il tuo codice ma mi ha dato un valore nullo come risposta. Sto parlando diContextLoader.getCurrentWebApplicationContext()
R. Karlus

9

Aggiungilo al tuo codice

@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;

Questo inietterà semplicemente myClass nella tua applicazione


6

sulla base della risposta di Vivek, ma penso che sarebbe meglio:

@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);
    }
}

Scrivere da un metodo di istanza a un campo statico è una cattiva pratica e pericolosa se vengono manipolate più istanze.


C'è l' org.springframework.core.io.ContextResourceinterfaccia. Suggerirei di scegliere un nome diverso per la classe interna ContextResourcesolo per evitare confusione.
Alexander Radchenko

@AlexanderRadchenko Ok, l'ho cambiato in InnerContextResource
Juan

1

Esistono molti modi per ottenere il contesto dell'applicazione nell'applicazione Spring. Questi sono riportati di seguito:

  1. Tramite 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;
    }
    }

Qui setApplicationContext(ApplicationContext applicationContext)metodo otterrai applicationContext

  1. Via Autowired :

    @Autowired
    private ApplicationContext applicationContext;

La @Autowiredparola chiave Here fornirà applicationContext.

Per maggiori informazioni visita questo thread

Grazie :)


0

Un altro modo è iniettare applicationContext tramite servlet.

Questo è un esempio di come iniettare dipendenze quando si utilizzano i servizi Web Spring.

<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>

Un modo alternativo è aggiungere il contesto dell'applicazione nel tuo web.xml come mostrato di seguito

<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>

Fondamentalmente stai cercando di dire al servlet che dovrebbe cercare i bean definiti in questi file di contesto.


0

Passaggio 1 : inserisci il seguente codice in classe

@Autowired
private ApplicationContext _applicationContext;

Passaggio 2 : scrivi Getter e Setter

Passaggio 3 : definire autowire = "byType" nel file xml in cui è definito il bean


0

Anche dopo aver aggiunto @Autowire se la tua classe non è un RestController o una classe di configurazione, l'oggetto applicationContext diventava nullo. Ho provato a creare una nuova classe con di seguito e funziona bene:

@Component
public class SpringContext implements ApplicationContextAware{

   private static ApplicationContext applicationContext;

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

puoi quindi implementare un metodo getter nella stessa classe secondo le tue necessità come ottenere il riferimento alla classe implementata da:

    applicationContext.getBean(String serviceName,Interface.Class)

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

Quindi puoi recuperare il fagiolo:

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

Riferimento: springbyexample.org


25
Questa risposta non ti dà il contesto corrente , piuttosto crea un'altra istanza.
Jaroslav Záruba
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.