在Spring中的多个事件上使用@EventListener注释

pik*_*ike 6 java events spring spring-mvc event-listener

这似乎是一个非常直截了当的问题,但我似乎无法在任何地方找到答案.

在Spring中,我可以使用@EventListener注释为事件创建一个侦听器,如下所示:

@Component
public class MyListener {

    @EventListener
    public void handleEvent(ContextRefreshedEvent event) {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我需要相同的方法来监听多个事件并根据发生的事件采取不同的行动呢?

直觉上,我在想类似的东西:

    @Component
    public class MyListener {

        @EventListener
        public void handleEvents(ContextRefreshedEvent event, ContextStopped event) {
             String event;
             if(event instanceof ContextRefreshedEvent)
                  event = "Refreshed";
             if(event instanceof ContextStoppedEvent)
                  event = "Stopped";
        }
    }
Run Code Online (Sandbox Code Playgroud)

EventListener注释监听多个事件的正确方法是什么?同一方法如何根据发生的实际事件进行区分?

非常感谢.

Ben*_*n M 11

名义上很容易创建一个侦听多个事件的事件监听器:

@EventListener({EventA.class, EventB.class})
public doSomething() {
   ...
}
Run Code Online (Sandbox Code Playgroud)

但显然这种方法不能让您访问基础事件.基于javadoc,EventListener它似乎不可能做你所建议的

如果带注释的方法支持单个事件类型,则该方法可以声明反映要侦听的事件类型的单个参数.如果带注释的方法支持多种事件类型,则此批注可以使用classes属性引用一个或多个受支持的事件类型.有关更多详细信息,请参阅classes()javadoc.

...

如果classes使用单个值指定( )属性,则带注释的方法可以选择接受单个参数.但是,如果使用多个值指定此属性,则带注释的方法不得声明任何参数.

因此,似乎没有任何机制来消耗多个事件并根据这些事件的主体采取不同的操作.我建议这不应该是必要的,你可以随时注册特定于事件的@EventListener方法,然后让它们调用共享方法来执行任何常见功能.

资料来源:https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/event/EventListener.html


小智 5

从Spring 4.2开始,您可以在方法声明中使用子类来处理所有扩展该子类的事件:

@EventListener
public void handleEvent(ApplicationEvent event) {
  // listen all descendants of the ApplicationEvent
}
Run Code Online (Sandbox Code Playgroud)

另外,您可以通过使用注释的属性来缩小事件列表:

@EventListener({ContextRefreshedEvent.class, ApplicationReadyEvent.class})
public void handleEvent(Object event) {
  // listen only ContextRefreshedEvent and ApplicationReadyEvent
}
Run Code Online (Sandbox Code Playgroud)


Ind*_*nde 5

你为什么不做这样的事情呢。

从 开始SpringFramework 4.2,您可以发布事件而无需扩展ApplicationEvent

正如您回答的那样,您主要想听自定义事件。你可以做这样的事情。

创建一个名为 的基类BaseEvent

public class BaseEvent {

  private String type;

  public BaseEvent() {}

  public String getType() {
    return type;
  }

  public void setType(String type) {
    this.type = type;
  }
}
Run Code Online (Sandbox Code Playgroud)

每当您想要发布自定义Event.

Example1Event现在让我们创建两个名为和 的自定义事件Example2Event

Example1Event班级

public class Example1Event extends BaseEvent {

  private String message;

  public Example1Event() {}

  public String getMessage() {
    return message;
  }

  public void setMessage(String message) {
    this.message = message;
  }
}
Run Code Online (Sandbox Code Playgroud)

Example2Event班级

public class Example2Event extends BaseEvent {

  private String message;

  public Example2Event() {}

  public String getMessage() {
    return message;
  }

  public void setMessage(String message) {
    this.message = message;
  }
}
Run Code Online (Sandbox Code Playgroud)

你的EventListener看起来像这样。

public class EventReceiver {

  public EventReceiver() {}

  @EventListener
  public void receiveEvent(BaseEvent event) {
    String eventType = event.getType();
    if (eventType.equals("example1")) {
      Example1Event example1Event = (Example1Event) event;
      System.out.println(example1Event.getMessage());
    } else if (eventType.equals("example2")) {
      Example2Event example2Event = (Example2Event) event;
      System.out.println(example2Event.getMessage());
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这将适合您想做的事情。


use*_*188 5

您可以为每个单独的事件设置多个 EventListener。