Java 如何将Spring应用程序上下文事件连接到其他上下文
我有一个SpringWeb应用程序,它有两个上下文:一个是由Java 如何将Spring应用程序上下文事件连接到其他上下文,java,spring,events,Java,Spring,Events,我有一个SpringWeb应用程序,它有两个上下文:一个是由ContextLoaderListener构建的(applicationContext),另一个是由DispatcherServlet构建的(webContext) 在applicationContext中有一个bean(org.springframework.security.authentication.DefaultAuthenticationEventPublisher)触发spring上下文事件 但是事件的接收者是在webCo
ContextLoaderListener
构建的(applicationContext
),另一个是由DispatcherServlet
构建的(webContext
)
在applicationContext
中有一个bean(org.springframework.security.authentication.DefaultAuthenticationEventPublisher
)触发spring上下文事件
但是事件的接收者是在webContext
中定义的。而那个接受者没有得到这个事件。(如果将用于测试的接收器放在applicationContext
中,则它将获得事件,但我无法这样做,因为我需要webContext
s来实现其功能。)
因此,我的问题是,如何将事件从
applicationContext
连接到webContext
?尝试将事件发布者移动到web上下文文件,在该文件中,它应该可以看到整个应用程序上下文。类似的问题也发生在以下情况下。父应用程序上下文(由ContextLoaderListener
加载)不知道子(web)上下文
如果您不真正需要两个应用程序之间的父子关系,也可以对整个应用程序使用单个应用程序上下文。通常情况下,这只是一种阻碍,如果所有bean都在同一个空间中定义,那么就更容易了。正如spring框架文档中所述,简单的ApplicationEvent机制只设计用于相同的应用程序上下文,我不知道可以将事件传播到子上下文 如果您需要更高级的解决方案,您可以考虑使用更增强的解决方案,如Java消息服务或Spring集成
我们可以使用import标记导入/桥接以事件/bean的可见性可用和共享的方式创建的两个不同上下文
<import resource="applicationContext_name.xml"/>
在此导入配置为从DispatcherServlet的上下文xml中的ContextLoaderListener创建的上下文xml。我认为实际的答案是,您可能希望以不同的方式配置应用程序(因此您只有一个上下文) 我认为在web.xml中,您需要执行以下操作:
<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>
例子
org.springframework.web.servlet.DispatcherServlet
1.
上下文配置位置
类路径:/META-INF/ApplicationsSpringConfig.xml
但要回答更深层次的问题。其他人指出,您可以在spring文件中使用include(实际上,在上面的示例中,您可以在DispatcherServlet中指定多个springconfig)。
但是,当您包含其他上下文文件时,您不会共享bean的实例,只共享定义
与EJB等相比,模块化Spring应用程序是Spring唯一真正的缺点,这导致Spring使用OSGi。
对于如何共享spring上下文这一基本问题的答案,您正式使用OSGi(spring dm)在上下文之间共享spring bean实例。我也遇到了同样的问题,通过将创建事件的bean移动到web上下文解决了我的问题。但是,您可以通过手动连接事件侦听器来解决问题,类似这样的方式(此代码未编译,因此未经测试):
@组件
公共类BeanWebContext实现ApplicationListener{
@自动连线
私有应用程序上下文网络上下文;
@施工后
公共无效注册表侦听器(){
//获取父上下文
AbstractApplicationContext appContext=(AbstractApplicationContext)webContext.getParent();
//将self注册为侦听器,此方法位于AbstractApplicationContext中
appContext.addApplicationListener(此);
}
@凌驾
Application event(SomeEvent)上的公共无效{
}
}
这不是解决方案,因为问题是如何处理这两种情况。(我不能在web上下文中移动安全性内容,因为我明确在应用程序中使用它(它是一个具有ACL的应用程序))。您实际上需要两个单独的应用程序上下文吗?这听起来像是一种只需要一个就可以更简单的情况。这听起来好多了。我将检查为什么使用两个上下文,并查看是否可以合并它们。两个上下文通常是默认设置。或者,您可以使用DispatcherServlet
context use import语句添加其他上下文文件。需要两个上下文(在我的例子中),因为某些筛选器需要父上下文(Spring Security的DelegatingFilterProxy,…)@See你找到解决问题的方法了吗?我猜Spring不允许你这么做。否则,如果您正在调试哪个类处理了事件,会不会很混乱?现在,不要只看一个容器,而要看所有容器
@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) {
}
}