如何将Spring Application Context事件与其他上下文联系起来

时间:2011-12-16 12:35:01

标签: java spring events

我有一个包含两个上下文的Spring Web应用程序:一个(applicationContext)由ContextLoaderListener构建,另一个(webContext)由DispatcherServlet构建。

applicationContext内是一个bean(org.springframework.security.authentication.DefaultAuthenticationEventPublisher),用于触发spring上下文事件。

但事件的接收者在webContext中定义。那个接收器没有得到这个事件。 (如果在applicationContext中将接收器用于测试目的,那么它就会得到事件,但我不能这样做,因为我需要webContext来实现它的功能。)

所以我的问题是,如何将事件从applicationContext桥接到webContext

5 个答案:

答案 0 :(得分:9)

我有同样的问题,通过将创建事件的bean移动到web上下文来解决我的问题。但是,您可以通过手动连接事件监听器来解决您的问题,这样的事情(此代码未编译,因此未经测试):

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

}

答案 1 :(得分:4)

我认为实际的答案是您可能希望以不同方式配置您的应用程序(这样您只有一个上下文) 我想在你的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>

但回答更深层次的问题。其他人指出你可以在spring文件中使用includes(事实上在上面你可以在你的调度程序servlet中指定多个springconfig)。 但是当你包含其他上下文文件时,你不共享bean的实例,只有定义。

与EJB等相比,模块化Spring应用程序是春天唯一真正的缺点。这导致了使用OSGi。 关于如何共享spring上下文的基本问题的答案,正式你使用OSGi(spring dm)在上下文之间共享spring bean实例

答案 2 :(得分:3)

尝试将事件发布者移动到Web上下文文件,在该文件中,它应该可以看到整个应用程序上下文。 configuring method security in the parent application context时出现类似问题。父应用程序上下文(由ContextLoaderListener加载)不知道子(web)上下文。

如果您真的不需要两者之间的父子关系,也可以为整个应用程序使用单个应用程序上下文。通常情况下它会阻碍,如果所有bean都在同一个空间中定义,那就更容易了。

答案 3 :(得分:3)

正如spring框架的文档中所述,简单的ApplicationEvent机制仅设计用于同一应用程序上下文中,我不知道可以将事件传播到子上下文。

如果您需要更高级的解决方案,可以考虑使用更强大的解决方案,如Java Message Service或Spring Integration。

http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#context-functionality-events

答案 4 :(得分:0)

我们可以使用import标签导入/桥接以事件/ bean的可见性可用和共享的方式创建的两个不同的上下文。

<import resource="applicationContext_name.xml"/>

在此导入中,配置为在DispatcherServlet的上下文xml中从ContextLoaderListener创建的上下文xml。