Java 如何将Spring应用程序上下文事件连接到其他上下文

Java 如何将Spring应用程序上下文事件连接到其他上下文,java,spring,events,Java,Spring,Events,我有一个SpringWeb应用程序,它有两个上下文:一个是由ContextLoaderListener构建的(applicationContext),另一个是由DispatcherServlet构建的(webContext) 在applicationContext中有一个bean(org.springframework.security.authentication.DefaultAuthenticationEventPublisher)触发spring上下文事件 但是事件的接收者是在webCo

我有一个SpringWeb应用程序,它有两个上下文:一个是由
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) {
    }

}