¿Hay alguna manera de solicitar estática / globalmente una copia del ApplicationContext en una aplicación Spring?
Suponiendo que la clase principal se inicia e inicializa el contexto de la aplicación, ¿tiene que pasar eso a través de la pila de llamadas a cualquier clase que lo necesite, o hay una forma de que una clase solicite el contexto creado previamente? (¿Qué asumo tiene que ser un singleton?)
fuente
instance()
método singleton como fábrica. Sin embargo, creo que primero dejé que todo el código fuera del contenedor acceda al contenedor. Entonces ese código podría solicitar objetos del contenedor.Puede implementar
ApplicationContextAware
o simplemente usar@Autowired
:SpringBean
habráApplicationContext
inyectado, dentro del cual se instanciará este bean. Por ejemplo, si tiene una aplicación web con una jerarquía de contextos bastante estándar:y
SpringBean
se declara dentro del contexto principal, se inyectará el contexto principal; de lo contrario, si se declara dentro del contexto MVC, se inyectará el contexto MVC.fuente
@Inject
tambiénAquí hay una buena manera (no la mía, la referencia original está aquí: http://sujitpal.blogspot.com/2007/03/accessing-spring-beans-from-legacy-code.html
He usado este enfoque y funciona bien. Básicamente es un bean simple que contiene una referencia (estática) al contexto de la aplicación. Al hacer referencia a él en la configuración de primavera, se inicializa.
Echa un vistazo a la referencia original, está muy claro.
fuente
getBean
desde un código que se ejecuta durante una prueba de Unidad porque el contexto Spring no se configurará antes de que lo solicite. Es una condición de carrera que acabo de golpear hoy después de 2 años de usar con éxito este enfoque.Creo que podrías usar SingletonBeanFactoryLocator . El archivo beanRefFactory.xml contendría el contexto de aplicación real, sería algo así:
Y el código para obtener un bean del contexto de la aplicación de donde sea sería algo como esto:
El equipo de Spring desaconseja el uso de esta clase y yadayada, pero me ha quedado bien donde lo he usado.
fuente
Antes de implementar cualquiera de las otras sugerencias, hágase estas preguntas ...
Las respuestas a estas preguntas son más fáciles en ciertos tipos de aplicaciones (aplicaciones web, por ejemplo) que en otras, pero vale la pena preguntar de todos modos.
Acceder al ApplicationContext viola el principio de inyección de dependencia, pero a veces no tienes muchas opciones.
fuente
Si usa una aplicación web, también hay otra forma de acceder al contexto de la aplicación sin usar singletons usando un servletfilter y un ThreadLocal. En el filtro, puede acceder al contexto de la aplicación utilizando WebApplicationContextUtils y almacenar el contexto de la aplicación o los beans necesarios en TheadLocal.
Precaución: si olvida desarmar el ThreadLocal, obtendrá problemas desagradables al intentar desinstalar la aplicación. Por lo tanto, debe configurarlo e inmediatamente comenzar un intento que desarma el ThreadLocal en la parte final.
Por supuesto, esto todavía usa un singleton: ThreadLocal. Pero los frijoles reales ya no necesitan serlo. Incluso puede tener un alcance de solicitud, y esta solución también funciona si tiene múltiples WAR en una aplicación con las bibliotecas en el EAR. Aún así, puede considerar este uso de ThreadLocal tan malo como el uso de singletons simples. ;-)
¿Quizás Spring ya ofrece una solución similar? No encontré uno, pero no estoy seguro.
fuente
Fuente: http://sujitpal.blogspot.de/2007/03/accessing-spring-beans-from-legacy-code.html
fuente
Eche un vistazo a ContextSingletonBeanFactoryLocator . Proporciona accesores estáticos para controlar los contextos de Spring, suponiendo que se hayan registrado de ciertas maneras.
No es bonito y más complejo de lo que te gustaría, pero funciona.
fuente
Hay muchas formas de obtener el contexto de la aplicación en la aplicación Spring. Esos se dan a continuación:
Vía ApplicationContextAware :
Aquí
setApplicationContext(ApplicationContext applicationContext)
método obtendrá el applicationContextVía Autowired :
Aquí la
@Autowired
palabra clave proporcionará el contexto de la aplicación. Autowired tiene algún problema. Creará un problema durante las pruebas unitarias.fuente
Tenga en cuenta que al almacenar cualquier estado desde el actual
ApplicationContext
o elApplicationContext
propio en una variable estática, por ejemplo, utilizando el patrón singleton, hará que sus pruebas sean inestables e impredecibles si está usando Spring-test. Esto se debe a que Spring-test almacena en caché y reutiliza contextos de aplicación en la misma JVM. Por ejemplo:@ContextConfiguration({"classpath:foo.xml"})
.@ContextConfiguration({"classpath:foo.xml", "classpath:bar.xml})
@ContextConfiguration({"classpath:foo.xml"})
Cuando se ejecuta la Prueba A,
ApplicationContext
se crea un an , y cualquierApplicationContextAware
beanApplicationContext
que implemente o se conecte automáticamente podría escribir en la variable estática.Cuando se ejecuta la Prueba B, sucede lo mismo y la variable estática ahora apunta a la Prueba B
ApplicationContext
Cuando Ensayo C se ejecuta, no hay granos se crean como el
TestContext
(y en el presente documento laApplicationContext
) de prueba A se resused. Ahora tiene una variable estática que apunta a otraApplicationContext
que no es la que actualmente contiene los beans para su prueba.fuente
No estoy seguro de lo útil que será, pero también puede obtener el contexto cuando inicializa la aplicación. Esto es lo más pronto que puede obtener el contexto, incluso antes de un
@Autowire
.fuente
Tenga en cuenta que; El siguiente código creará un nuevo contexto de aplicación en lugar de utilizar el ya cargado.
También tenga en cuenta que
beans.xml
debe ser parte de lossrc/main/resources
medios en la guerra que es parte deWEB_INF/classes
, ya que la aplicación real se cargará a través deapplicationContext.xml
mencionado enWeb.xml
.Es difícil mencionar la
applicationContext.xml
ruta en elClassPathXmlApplicationContext
constructor.ClassPathXmlApplicationContext("META-INF/spring/applicationContext.xml")
No podrá localizar el archivo.Por lo tanto, es mejor usar applicationContext existente mediante anotaciones.
fuente
Sé que esta pregunta está respondida, pero me gustaría compartir el código de Kotlin que hice para recuperar el Contexto de Primavera.
No soy especialista, por lo que estoy abierto a críticas, críticas y consejos:
https://gist.github.com/edpichler/9e22309a86b97dbd4cb1ffe011aa69dd
Ahora, un contexto de primavera está disponible públicamente, pudiendo llamar al mismo método independientemente del contexto (pruebas junit, beans, clases instanciadas manualmente) como en este Java Servlet:
fuente
Realice el cableado automático en Spring Bean de la siguiente manera: @Autowired private ApplicationContext appContext;
será el objeto applicationcontext.
fuente
Enfoque 1: puede inyectar ApplicationContext implementando la interfaz ApplicationContextAware. Referencia enlace .
Enfoque 2: contexto de aplicación de autowire en cualquiera de los beans gestionados por Spring.
Referencia enlace .
fuente