我有一个关于Spring的ApplicationListener在父子上下文方面的性质的问题。假设您创建了一个父上下文,该上下文创建了一个单例并注册为ApplicationListener的bean。然后,稍后使用父上下文创建子上下文。当关闭子上下文时,Spring将发出ContextClosedEvent。此事件是否传播到父上下文,也导致所有作为ApplicationListeners的父上下文单例接收该事件?

我在文档中注意到[ContextClosedEvent]:(http://docs.spring.io/spring/docs/4.0.6.RELEASE/spring-framework-reference/htmlsingle/#context-functionality-events),“使用ConfigurableApplicationContext接口上的close()方法关闭ApplicationContext时发布。此处的“ Closed”表示所有单例bean都被销毁。上下文已到使用寿命;无法刷新或重新启动。”

从本质上讲,我要问的是事件发布仅限于特定的子上下文,还是在所有父/子上下文中传播?

最佳答案

将调用所有侦听器,但是参数(在本例中为ContextClosedEvent)将指向要关闭的上下文。

以下测试创建一个父上下文,子上下文,启动它们,关闭父对象,然后关闭子对象。

public class ContextListenerTest {

    @Test
    public void contextListenerTest() {
        AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(ParentContext.class);
        AnnotationConfigApplicationContext child = new AnnotationConfigApplicationContext(ChildContext.class);
        child.setParent(parent);
        child.start();

        System.out.println("closing child now...");
        child.close();
        System.out.println("closing parent now...");
        parent.close();
    }

    public static class ParentContext {
        @Bean
        public ApplicationListener<ContextClosedEvent> closeEvent() {
            return new ApplicationListener<ContextClosedEvent>() {
                @Override
                public void onApplicationEvent(ContextClosedEvent event) {
                    System.out.println("parent listener: " + event);
                }
            };
        }
    }

    public static class ChildContext {
        @Bean
        public ApplicationListener<ContextClosedEvent> closeEvent() {
            return new ApplicationListener<ContextClosedEvent>() {
                @Override
                public void onApplicationEvent(ContextClosedEvent event) {
                    System.out.println("child listener: " + event);
                }
            };
        }
    }

}


提供的测试将输出以下文本:

closing child now...
child listener: org.springframework.context.event.ContextClosedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@3f1b7a14: startup date [Mon Jul 21 15:25:23 BRT 2014]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@94ac7e0]
parent listener: org.springframework.context.event.ContextClosedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@3f1b7a14: startup date [Mon Jul 21 15:25:23 BRT 2014]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@94ac7e0]
closing parent now...
parent listener: org.springframework.context.event.ContextClosedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@94ac7e0: startup date [Mon Jul 21 15:25:22 BRT 2014]; root of context hierarchy]


在第一个关闭(子)中,两个侦听器均被执行。但是您可以获得使用event.getApplicationContext()关闭的上下文。

08-04 19:14