Spring obtenir le contexte d'application actuel

105

J'utilise Spring MVC pour mon application Web. Mes beans sont écrits dans le spring-servlet.xmlfichier " "

Maintenant, j'ai une classe MyClasset je veux accéder à cette classe en utilisant Spring Bean

Dans le spring-servlet.xmlj'ai écrit suivant

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

Maintenant, je dois y accéder en utilisant ApplicationContext

ApplicationContext context = ??

Pour que je puisse faire

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

Comment faire ça ??

LynAs
la source
3
@Autowired MyClass myClass devrait faire le travail!
Mannekenpix

Réponses:

161

Injectez-le simplement.

@Autowired
private ApplicationContext appContext;

ou implémentez cette interface: ApplicationContextAware

gipinani
la source
Peut-être que cela peut fonctionner: stackoverflow.com/questions/11682858/…
gipinani
La ApplicationContextProvider.javaréponse suivante semble être la solution la plus fiable pour cela.
Ionut
1
Il renvoie NULL à chaque fois. Pour mentionner ici que je fais cela dans une classe normale qui n'est ni un "@RestController" ni un "@Component"
zulkarnain shah
1
Selon la documentation de Spring, il est préférable d'éviter @Autowired en raison de certains problèmes. Voici le lien spring.io/understanding/application-context . La meilleure option consiste à implémenter l'interface ApplicationContextAware.
Durja Arai
89

Je pense que ce lien montre le meilleur moyen d'obtenir le contexte d'application n'importe où, même dans la classe non-bean. Je trouve cela très utile. J'espère que c'est la même chose pour vous. Le ci-dessous est le code abstrait de celui-ci

Créer une nouvelle 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;
    }
}

Ajouter une entrée dans application-context.xml

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

Dans le cas des annotations (au lieu de application-context.xml)

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

Obtenez le contexte comme celui-ci

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

À votre santé!!

Vivek
la source
1
J'ai codé similaire à Vivek. Mais j'évite de créer un nouveau ApplicationContextProvider () chaque fois que je dois appeler le getBean () à partir du contexte. Ce que j'ai fait, c'est d'avoir une ApplicationContextProvider.getApplicationContext() méthode statique . Ensuite, quand il est temps d'avoir besoin du contexte actuel de l'application, j'invoque:ApplicationContextProvider appContext = ApplicationContextProvider.getApplicationContext()
Panini Luncher
1
Oui Panini Luncher, ce serait toujours bien. Selon votre suggestion, je vais le changer de cette façon. :)
Vivek
4
Ajouter @Componentsur la ApplicationContextProviderconfiguration peut éviter d'enaplication-context.xml
bluearrow
1
Remarque: le getter et le setter de contexte doivent être synchronisés. Vous éviterez beaucoup de maux de tête spécialement pour les tests unitaires / d'intégration. Dans mon cas, ApplicationContextProvider similaire contenait un ancien contexte (du test d'intégration précédent) qui causait de nombreux bogues délicats.
Oleksandr_DJ
43

Au cas où vous auriez besoin d'accéder au contexte depuis un HttpServlet qui lui-même n'est pas instancié par Spring (et donc ni @Autowire ni ApplicationContextAware ne fonctionneront) ...

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

ou

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

En ce qui concerne certaines des autres réponses, réfléchissez à deux fois avant de faire ceci:

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

... comme cela ne vous donne pas le contexte actuel, cela crée plutôt une autre instance de celui-ci pour vous. Ce qui signifie que 1) une partie importante de la mémoire et 2) les beans ne sont pas partagés entre ces deux contextes d'application.

Jaroslav Záruba
la source
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (this) - a fait le travail pour moi dans la méthode init () du filtre d'action du portlet Liferay.
Igor Baiborodine
Génial, le processInjectionBasedOnCurrentContext a fait tout le travail dont j'avais besoin. Merci beaucoup @Jaroslav
Jad B.
ApplicationContextAware fonctionne pour moi, quand il est annoté avec @Component comme dans la solution de Vivek (j'initialise le contexte Spring manuellement en étendant AbstractContextLoaderInitializer / createRootApplicationContext)
hello_earth
Soyez averti ... SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (this); ne se produit pas immédiatement, vous ne pouvez donc pas l'utiliser comme première ligne dans votre constructeur par exemple.
SledgeHammer le
31

Si vous implémentez une classe qui n'est pas instanciée par Spring, comme un JsonDeserializer, vous pouvez utiliser:

WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
MyClass myBean = context.getBean(MyClass.class);
rzymek
la source
8
Cela ne fonctionne pas pour moi. Ma classe est hors du contexte du printemps. J'ai essayé d'utiliser votre code mais il me donne une réponse nulle . Je parle deContextLoader.getCurrentWebApplicationContext()
R. Karlus
9

Ajoutez ceci à votre code

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

Cela injectera simplement myClass dans votre application

Hitesh Kumar
la source
6

basé sur la réponse de Vivek, mais je pense que ce qui suit serait mieux:

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

L'écriture d'une méthode d'instance vers un champ statique est une mauvaise pratique et dangereuse si plusieurs instances sont manipulées.

Juan
la source
Il y a une org.springframework.core.io.ContextResourceinterface. Je suggérerais de choisir un nom différent pour la classe intérieure ContextResourcejuste pour éviter le désordre.
Alexander Radchenko
@AlexanderRadchenko Ok, je l'ai changé en InnerContextResource
Juan
1

Il existe de nombreuses façons d'obtenir le contexte de l'application dans l'application Spring. Ceux-ci sont donnés ci-dessous:

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

Ici setApplicationContext(ApplicationContext applicationContext), vous obtiendrez l'applicationContext

  1. Via Autowired :

    @Autowired
    private ApplicationContext applicationContext;

Ici, le @Autowiredmot-clé fournira l'applicationContext.

Pour plus d'informations, visitez ce fil

Merci :)

Md. Sajedul Karim
la source
0

Une autre méthode consiste à injecter applicationContext via un servlet.

Voici un exemple de la façon d'injecter des dépendances lors de l'utilisation des services 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>

Une autre façon consiste à ajouter un contexte d'application dans votre web.xml comme indiqué ci-dessous

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

En gros, vous essayez de dire au servlet qu'il doit rechercher les beans définis dans ces fichiers de contexte.

vsingh
la source
0

Étape 1 : Injectez le code suivant en classe

@Autowired
private ApplicationContext _applicationContext;

Étape 2 : Écrivez Getter & Setter

Étape 3 : définir autowire = "byType" dans le fichier xml dans lequel le bean est défini

Kamlesh Paunikar
la source
0

Même après avoir ajouté @Autowire si votre classe n'est pas un RestController ou une classe de configuration, l'objet applicationContext devenait nul. J'ai essayé de créer une nouvelle classe avec ci-dessous et cela fonctionne bien:

@Component
public class SpringContext implements ApplicationContextAware{

   private static ApplicationContext applicationContext;

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

vous pouvez ensuite implémenter une méthode getter dans la même classe selon vos besoins, comme obtenir la référence de classe implémentée en:

    applicationContext.getBean(String serviceName,Interface.Class)
Aman Malhotra
la source
-11
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-servlet.xml");

Ensuite, vous pouvez récupérer le bean:

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

Référence: springbyexample.org

PraZ
la source
25
Cette réponse ne vous donne pas le contexte actuel , elle crée plutôt une autre instance.
Jaroslav Záruba