Spring obtiene ApplicationContext actual

105

Estoy usando Spring MVC para mi aplicación web. Mis frijoles están escritos en el spring-servlet.xmlarchivo " "

Ahora tengo una clase MyClassy quiero acceder a esta clase usando spring bean

En el spring-servlet.xmlhe escrito siguiendo

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

Ahora necesito acceder a esto usando ApplicationContext

ApplicationContext context = ??

Para que yo pueda hacer

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

¿¿Como hacer esto??

LynAs
fuente
3
@Autowired MyClass myClass debería hacer el trabajo!
Mannekenpix

Respuestas:

160

Simplemente inyéctelo ..

@Autowired
private ApplicationContext appContext;

o implementar esta interfaz: ApplicationContextAware

gipinani
fuente
Tal vez esto pueda funcionar: stackoverflow.com/questions/11682858/…
gipinani
La siguiente ApplicationContextProvider.javarespuesta parece ser la solución más confiable para esto.
Ionut
1
Devuelve NULL cada vez. Para mencionar aquí que estoy haciendo esto dentro de una clase normal que no es ni "@RestController" ni "@Component"
zulkarnain shah
1
Según la documentación de Spring, es mejor evitar @Autowired debido a algunos problemas. Aquí está el enlace spring.io/understanding/application-context . La mejor opción es implementar la interfaz ApplicationContextAware.
Durja Arai
89

Creo que este enlace demuestra la mejor manera de obtener el contexto de la aplicación en cualquier lugar, incluso en la clase que no es bean. Me resulta muy útil. Espero que sea lo mismo para ti. El siguiente es el código abstracto de la misma.

Cree una nueva clase 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;
    }
}

Agregue una entrada en application-context.xml

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

En caso de anotaciones (en lugar de application-context.xml)

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

Obtén el contexto como este

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

¡¡Salud!!

Vivek
fuente
1
Codifiqué similar a Vivek. Pero evito crear un nuevo ApplicationContextProvider () cada vez que necesito llamar a getBean () desde el contexto. Lo que hice fue tener método estático ApplicationContextProvider.getApplicationContext() . Luego, cuando llega el momento de necesitar el contexto actual de la aplicación, invoco:ApplicationContextProvider appContext = ApplicationContextProvider.getApplicationContext()
Panini Luncher
1
Sí Panini Luncher, eso aún sería bueno. Según su sugerencia, lo cambiaré de esa manera. :)
Vivek
4
Añadir @Componenten ApplicationContextProviderla configuración puede evitar enaplication-context.xml
bluearrow
1
Nota: el captador y el definidor de contexto deben estar sincronizados. Evitará muchos dolores de cabeza especialmente para pruebas unitarias / de integración. En mi caso, ApplicationContextProvider similar tenía un contexto antiguo (de la prueba de integración anterior) que causó muchos errores complicados.
Oleksandr_DJ
43

En caso de que necesite acceder al contexto desde dentro de un HttpServlet que Spring no instancia en sí mismo (y por lo tanto, ni @Autowire ni ApplicationContextAware funcionarán) ...

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

o

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

En cuanto a algunas de las otras respuestas, piénselo dos veces antes de hacer esto:

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

... ya que esto no le da el contexto actual, sino que crea otra instancia del mismo para usted. Lo que significa que 1) una cantidad significativa de memoria y 2) los beans no se comparten entre estos dos contextos de aplicación.

Jaroslav Záruba
fuente
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (this) - hizo el trabajo por mí en el método init () del filtro de acción del portlet Liferay.
Igor Baiborodine
Impresionante, el processInjectionBasedOnCurrentContext hizo todo el trabajo que necesitaba. Muchas gracias @Jaroslav
Jad B.
ApplicationContextAware SÍ funciona para mí, cuando está anotado con @Component como en la solución de Vivek (estoy inicializando el contexto de Spring manualmente mediante la extensión de AbstractContextLoaderInitializer / createRootApplicationContext)
hello_earth
Tenga cuidado ... SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (this); no sucede de inmediato, por lo que no puede usarlo como la primera línea en su constructor, por ejemplo.
SledgeHammer
31

Si está implementando una clase que no es instanciada por Spring, como un JsonDeserializer, puede usar:

WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
MyClass myBean = context.getBean(MyClass.class);
rzymek
fuente
8
No me funciona. Mi clase está fuera del contexto de Spring. Intenté usar su código pero me dio un nulo como respuesta. Estoy hablando deContextLoader.getCurrentWebApplicationContext()
R. Karlus
9

Agrega esto a tu código

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

Esto simplemente inyectará myClass en su aplicación

Hitesh Kumar
fuente
6

basado en la respuesta de Vivek, pero creo que lo siguiente sería mejor:

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

Escribir desde un método de instancia en un campo estático es una mala práctica y peligrosa si se manipulan varias instancias.

Juan
fuente
Hay org.springframework.core.io.ContextResourceinterfaz. Sugeriría elegir un nombre diferente para la clase interna ContextResourcesolo para evitar desorden.
Alexander Radchenko
@AlexanderRadchenko Ok, lo cambié a InnerContextResource
Juan
1

Hay muchas formas de obtener el contexto de la aplicación en la aplicación Spring. Los que se dan a continuación:

  1. A través de 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;
    }
    }

Aquí el setApplicationContext(ApplicationContext applicationContext)método obtendrá el applicationContext

  1. A través de Autowired :

    @Autowired
    private ApplicationContext applicationContext;

aquí @Autowired palabra clave proporcionará el applicationContext.

Para más información visite este hilo

Gracias :)

Md. Sajedul Karim
fuente
0

Otra forma es inyectar applicationContext a través de servlet.

Este es un ejemplo de cómo inyectar dependencias al usar los servicios web de 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>

La forma alternativa es agregar el contexto de la aplicación en su web.xml como se muestra a continuación

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

Básicamente, está intentando decirle al servlet que debe buscar beans definidos en estos archivos de contexto.

vsingh
fuente
0

Paso 1 : inyecte el siguiente código en clase

@Autowired
private ApplicationContext _applicationContext;

Paso 2 : Escribe Getter & Setter

Paso 3 : defina autowire = "byType" en el archivo xml en el que se define el bean

Kamlesh Paunikar
fuente
0

Incluso después de agregar @Autowire si su clase no es un RestController o una clase de configuración, el objeto applicationContext era nulo. Intenté crear una nueva clase con la siguiente y está funcionando bien:

@Component
public class SpringContext implements ApplicationContextAware{

   private static ApplicationContext applicationContext;

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

luego puede implementar un método getter en la misma clase según su necesidad, como obtener la referencia de clase implementada mediante:

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

Entonces puedes recuperar el bean:

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

Referencia: springbyexample.org

PraZ
fuente
25
Esta respuesta no le da el contexto actual , sino que crea otra instancia.
Jaroslav Záruba