java - docs - pagecontext jstl
Cómo unir los eventos del contexto de la aplicación Spring a otro contexto (5)
Tengo una aplicación web Spring con dos contextos: uno ( applicationContext
) creado por ContextLoaderListener
y un segundo ( webContext
) creado por DispatcherServlet
.
Dentro del applicationContext
hay un bean ( org.springframework.security.authentication.DefaultAuthenticationEventPublisher
) que org.springframework.security.authentication.DefaultAuthenticationEventPublisher
eventos de contexto de resorte.
Pero el receptor para el evento está definido en el webContext
. Y ese receptor no consiguió el evento. (Si coloca el receptor con fines de prueba en el applicationContext
entonces obtendrá el evento, pero no puedo hacer esto, porque necesito los webContext
s para su funcionalidad).
Así que mi pregunta es, ¿cómo se webContext
los eventos desde la applicationContext
a webContext
?
Como se indica en la documentación para el marco de Spring, el simple mecanismo ApplicationEvent solo está diseñado para ser utilizado dentro del mismo contexto de aplicación, no tengo conocimiento de que sea posible propagar eventos a contextos secundarios.
Si necesita una solución más avanzada, podría considerar el uso de una solución mejorada como Java Message Service o Spring Integration.
Creo que la respuesta real es que es posible que desee configurar su aplicación de manera diferente (para que solo tenga un contexto) Creo que en su web.xml necesita hacer algo como esto:
<servlet>
<servlet-name>example</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:/META-INF/applicationSpringConfig.xml
</param-value>
</init-param>
</servlet>
Pero para responder a la pregunta más profunda. Alguien más señala que puede usar los archivos incluidos en su archivo de Spring (de hecho, en lo anterior puede tener más de un springconfig especificado en su servlet de despachador). Pero cuando incluye otros archivos de contexto, no comparte instancias de beans, solo definiciones.
La modularización de las aplicaciones Spring ha sido la única desventaja real de la primavera en comparación con EJB, etc. Eso llevó a Spring a utilizar OSGi. Y la respuesta a su pregunta subyacente de cómo compartir el contexto de Spring, oficialmente usted comparte instancias de bean bean entre contextos usando OSGi (spring dm)
Intente mover el editor de eventos al archivo de contexto web, donde debería tener visibilidad sobre todo el contexto de la aplicación. Se produce un problema similar al configurar la seguridad del método en el contexto de la aplicación principal . El contexto de la aplicación principal (cargado por ContextLoaderListener
) no es consciente del contexto secundario (web).
También puede usar un solo contexto de aplicación para toda la aplicación si realmente no necesita la relación padre-hijo entre los dos. A menudo, solo interfiere en el camino y es más fácil si todos los beans se definieran en el mismo espacio.
Podemos usar la etiqueta de importación para importar / salvar los 2 contextos diferentes creados de forma que la visibilidad de los eventos / beans esté disponible y compartida.
<import resource="applicationContext_name.xml"/>
En esta importación, el contexto xml que está configurado para crearse desde ContextLoaderListener en el contexto xml del DispatcherServlet.
Tuve el mismo problema, resolví el mío moviendo los beans que creaban el evento al contexto web. Sin embargo, puede resolver su problema conectando manualmente su detector de eventos, algo como esto (este código no está compilado, por lo tanto, no está probado):
@Component
public class BeanInWebContext implements ApplicationListener<SomeEvent> {
@Autowired
private ApplicationContext webContext;
@PostConstruct
public void registerAsListener() {
// get parent context
AbstractApplicationContext appContext = (AbstractApplicationContext) webContext.getParent();
// register self as a listener, this method is in AbstractApplicationContext
appContext.addApplicationListener(this);
}
@Override
public void onApplicationEvent(SomeEvent event) {
}
}