@Test
  public void listenersInApplicationContextWithNestedChild() {
    StaticApplicationContext context = new StaticApplicationContext();
    RootBeanDefinition nestedChild = new RootBeanDefinition(StaticApplicationContext.class);
    nestedChild.getPropertyValues().add("parent", context);
    nestedChild.setInitMethodName("refresh");
    context.registerBeanDefinition("nestedChild", nestedChild);
    RootBeanDefinition listener1Def = new RootBeanDefinition(MyOrderedListener1.class);
    listener1Def.setDependsOn(new String[] {"nestedChild"});
    context.registerBeanDefinition("listener1", listener1Def);
    context.refresh();

    MyOrderedListener1 listener1 = context.getBean("listener1", MyOrderedListener1.class);
    MyEvent event1 = new MyEvent(context);
    context.publishEvent(event1);
    assertTrue(listener1.seenEvents.contains(event1));

    SimpleApplicationEventMulticaster multicaster =
        context.getBean(
            AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME,
            SimpleApplicationEventMulticaster.class);
    assertFalse(multicaster.getApplicationListeners().isEmpty());

    context.close();
    assertTrue(multicaster.getApplicationListeners().isEmpty());
  }
  @Test
  public void innerBeanAsListener() {
    StaticApplicationContext context = new StaticApplicationContext();
    RootBeanDefinition listenerDef = new RootBeanDefinition(TestBean.class);
    listenerDef.getPropertyValues().add("friends", new RootBeanDefinition(BeanThatListens.class));
    context.registerBeanDefinition("listener", listenerDef);
    context.refresh();

    context.publishEvent(new MyEvent(this));
    context.publishEvent(new MyEvent(this));
    TestBean listener = context.getBean(TestBean.class);
    assertEquals(3, ((BeanThatListens) listener.getFriends().iterator().next()).getEventCount());

    context.close();
  }
  @Test
  public void nonSingletonListenerInApplicationContext() {
    StaticApplicationContext context = new StaticApplicationContext();
    RootBeanDefinition listener = new RootBeanDefinition(MyNonSingletonListener.class);
    listener.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
    context.registerBeanDefinition("listener", listener);
    context.refresh();

    MyEvent event1 = new MyEvent(context);
    context.publishEvent(event1);
    MyOtherEvent event2 = new MyOtherEvent(context);
    context.publishEvent(event2);
    MyEvent event3 = new MyEvent(context);
    context.publishEvent(event3);
    MyOtherEvent event4 = new MyOtherEvent(context);
    context.publishEvent(event4);
    assertTrue(MyNonSingletonListener.seenEvents.contains(event1));
    assertTrue(MyNonSingletonListener.seenEvents.contains(event2));
    assertTrue(MyNonSingletonListener.seenEvents.contains(event3));
    assertTrue(MyNonSingletonListener.seenEvents.contains(event4));
    MyNonSingletonListener.seenEvents.clear();

    context.close();
  }
  @Test
  public void listenerAndBroadcasterWithCircularReference() {
    StaticApplicationContext context = new StaticApplicationContext();
    context.registerBeanDefinition("broadcaster", new RootBeanDefinition(BeanThatBroadcasts.class));
    RootBeanDefinition listenerDef = new RootBeanDefinition(BeanThatListens.class);
    listenerDef
        .getConstructorArgumentValues()
        .addGenericArgumentValue(new RuntimeBeanReference("broadcaster"));
    context.registerBeanDefinition("listener", listenerDef);
    context.refresh();

    BeanThatBroadcasts broadcaster = context.getBean("broadcaster", BeanThatBroadcasts.class);
    context.publishEvent(new MyEvent(context));
    assertEquals("The event was not received by the listener", 2, broadcaster.receivedCount);

    context.close();
  }
  @Test
  public void listenersInApplicationContext() {
    StaticApplicationContext context = new StaticApplicationContext();
    context.registerBeanDefinition("listener1", new RootBeanDefinition(MyOrderedListener1.class));
    RootBeanDefinition listener2 = new RootBeanDefinition(MyOrderedListener2.class);
    listener2
        .getConstructorArgumentValues()
        .addGenericArgumentValue(new RuntimeBeanReference("listener1"));
    listener2.setLazyInit(true);
    context.registerBeanDefinition("listener2", listener2);
    context.refresh();
    assertFalse(context.getDefaultListableBeanFactory().containsSingleton("listener2"));

    MyOrderedListener1 listener1 = context.getBean("listener1", MyOrderedListener1.class);
    MyOtherEvent event1 = new MyOtherEvent(context);
    context.publishEvent(event1);
    assertFalse(context.getDefaultListableBeanFactory().containsSingleton("listener2"));
    MyEvent event2 = new MyEvent(context);
    context.publishEvent(event2);
    assertTrue(context.getDefaultListableBeanFactory().containsSingleton("listener2"));
    MyEvent event3 = new MyEvent(context);
    context.publishEvent(event3);
    MyOtherEvent event4 = new MyOtherEvent(context);
    context.publishEvent(event4);
    assertTrue(listener1.seenEvents.contains(event1));
    assertTrue(listener1.seenEvents.contains(event2));
    assertTrue(listener1.seenEvents.contains(event3));
    assertTrue(listener1.seenEvents.contains(event4));

    listener1.seenEvents.clear();
    context.publishEvent(event1);
    context.publishEvent(event2);
    context.publishEvent(event3);
    context.publishEvent(event4);
    assertTrue(listener1.seenEvents.contains(event1));
    assertTrue(listener1.seenEvents.contains(event2));
    assertTrue(listener1.seenEvents.contains(event3));
    assertTrue(listener1.seenEvents.contains(event4));

    context.close();
  }