@Test
  public void orderedListenersWithAnnotation() {
    MyOrderedListener3 listener1 = new MyOrderedListener3();
    MyOrderedListener4 listener2 = new MyOrderedListener4(listener1);

    SimpleApplicationEventMulticaster smc = new SimpleApplicationEventMulticaster();
    smc.addApplicationListener(listener2);
    smc.addApplicationListener(listener1);

    smc.multicastEvent(new MyEvent(this));
    smc.multicastEvent(new MyOtherEvent(this));
  }
  @Test
  public void orderedListeners() {
    MyOrderedListener1 listener1 = new MyOrderedListener1();
    MyOrderedListener2 listener2 = new MyOrderedListener2(listener1);

    SimpleApplicationEventMulticaster smc = new SimpleApplicationEventMulticaster();
    smc.addApplicationListener(listener2);
    smc.addApplicationListener(listener1);

    smc.multicastEvent(new MyEvent(this));
    smc.multicastEvent(new MyOtherEvent(this));
  }
  private void multicastEvent(
      boolean match, Class<?> listenerType, ApplicationEvent event, ResolvableType eventType) {
    @SuppressWarnings("unchecked")
    ApplicationListener<ApplicationEvent> listener =
        (ApplicationListener<ApplicationEvent>) mock(listenerType);
    SimpleApplicationEventMulticaster smc = new SimpleApplicationEventMulticaster();
    smc.addApplicationListener(listener);

    if (eventType != null) {
      smc.multicastEvent(event, eventType);
    } else {
      smc.multicastEvent(event);
    }
    int invocation = match ? 1 : 0;
    verify(listener, times(invocation)).onApplicationEvent(event);
  }
  @Test
  @SuppressWarnings("unchecked")
  public void proxiedListeners() {
    MyOrderedListener1 listener1 = new MyOrderedListener1();
    MyOrderedListener2 listener2 = new MyOrderedListener2(listener1);
    ApplicationListener<ApplicationEvent> proxy1 =
        (ApplicationListener<ApplicationEvent>) new ProxyFactory(listener1).getProxy();
    ApplicationListener<ApplicationEvent> proxy2 =
        (ApplicationListener<ApplicationEvent>) new ProxyFactory(listener2).getProxy();

    SimpleApplicationEventMulticaster smc = new SimpleApplicationEventMulticaster();
    smc.addApplicationListener(proxy1);
    smc.addApplicationListener(proxy2);

    smc.multicastEvent(new MyEvent(this));
    smc.multicastEvent(new MyOtherEvent(this));
  }
  @Test
  public void simpleApplicationEventMulticasterWithErrorHandler() {
    @SuppressWarnings("unchecked")
    ApplicationListener<ApplicationEvent> listener = mock(ApplicationListener.class);
    ApplicationEvent evt = new ContextClosedEvent(new StaticApplicationContext());

    SimpleApplicationEventMulticaster smc = new SimpleApplicationEventMulticaster();
    smc.setErrorHandler(TaskUtils.LOG_AND_SUPPRESS_ERROR_HANDLER);
    smc.addApplicationListener(listener);

    willThrow(new RuntimeException()).given(listener).onApplicationEvent(evt);
    smc.multicastEvent(evt);
  }
  @Test
  public void simpleApplicationEventMulticasterWithException() {
    @SuppressWarnings("unchecked")
    ApplicationListener<ApplicationEvent> listener = mock(ApplicationListener.class);
    ApplicationEvent evt = new ContextClosedEvent(new StaticApplicationContext());

    SimpleApplicationEventMulticaster smc = new SimpleApplicationEventMulticaster();
    smc.addApplicationListener(listener);

    RuntimeException thrown = new RuntimeException();
    willThrow(thrown).given(listener).onApplicationEvent(evt);
    try {
      smc.multicastEvent(evt);
      fail("Should have thrown RuntimeException");
    } catch (RuntimeException ex) {
      assertSame(thrown, ex);
    }
  }
  @Test
  public void simpleApplicationEventMulticasterWithTaskExecutor() {
    @SuppressWarnings("unchecked")
    ApplicationListener<ApplicationEvent> listener = mock(ApplicationListener.class);
    ApplicationEvent evt = new ContextClosedEvent(new StaticApplicationContext());

    SimpleApplicationEventMulticaster smc = new SimpleApplicationEventMulticaster();
    smc.setTaskExecutor(
        new Executor() {
          @Override
          public void execute(Runnable command) {
            command.run();
            command.run();
          }
        });
    smc.addApplicationListener(listener);

    smc.multicastEvent(evt);
    verify(listener, times(2)).onApplicationEvent(evt);
  }