java 在 Spring 中对多个事件使用 @EventListener 注释

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/45884537/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 08:57:54  来源:igfitidea点击:

Use @EventListener annotation on multiple events in Spring

javaspringspring-mvceventsevent-listener

提问by pike

This seems like a pretty straight forward question, but I can't seem to find the answer anywhere.

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

In Spring, I can create a listener for an event using the @EventListener annotation, like this:

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

@Component
public class MyListener {

    @EventListener
    public void handleEvent(ContextRefreshedEvent event) {
        ...
    }
}

However, what if I need the same method to listen to multiple events and act differently based the event that happens?

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

Intuitively, I'm thinking something similar to this:

直觉上,我在想类似的事情:

    @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";
        }
    }

What is the correct way for the EventListener annotation to listen to multiple events and how can the same method differentiate based on the actual event that happens?

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

Thanks a lot.

非常感谢。

回答by Ben M

It's nominally easy to create an event listener that listens for multiple events:

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

@EventListener({EventA.class, EventB.class})
public doSomething() {
   ...
}

But obviously this approach does not give you access to the underlying event. Based on the javadoc for EventListenerit does not appear to be possible to do what you are suggesting

但显然这种方法不能让您访问底层事件。基于 javadoc 因为EventListener它似乎无法执行您的建议

If an annotated method supports a single event type, the method may declare a single parameter that reflects the event type to listen to. If an annotated method supports multiple event types, this annotation may refer to one or more supported event types using the classes attribute. See the classes() javadoc for further details.

...

If (the classes) attribute is specified with a single value, the annotated method may optionally accept a single parameter. However, if this attribute is specified with multiple values, the annotated method must not declare any parameters.

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

...

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

Thus there does not appear to be any mechanism to consume multiple events and take a different action based on the body of those events. I would suggest that this shouldn't be necessary though, you could always register event-specific @EventListenermethods, and then just have them call a shared method to perform any common functionality.

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

Source: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/event/EventListener.html

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

回答by Alexander Leshkin

Since Spring 4.2 you can use subclass in method declaration to handle all events those extends this subclass:

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

@EventListener
public void handleEvent(ApplicationEvent event) {
  // listen all descendants of the ApplicationEvent
}

Also you can narrow list of events by using annotion's attribute:

您也可以使用 annotion 的属性来缩小事件列表:

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

回答by Indraneel Bende

Why don't you do something like this.

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

From SpringFramework 4.2, you can publish events without extending ApplicationEvent.

SpringFramework 4.2,您可以在不扩展的情况下发布事件ApplicationEvent

As you replied you want to mostly listen to custom events. You can do something like this.

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

Create a Base class called BaseEvent.

创建一个名为BaseEvent.

public class BaseEvent {

  private String type;

  public BaseEvent() {}

  public String getType() {
    return type;
  }

  public void setType(String type) {
    this.type = type;
  }
}

Consider that as the base class whenever you want to publish a custom Event.

每当您想发布自定义Event.

Now lets create two custom events called Example1Eventand Example2Event.

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

Example1EventClass

Example1Event班级

public class Example1Event extends BaseEvent {

  private String message;

  public Example1Event() {}

  public String getMessage() {
    return message;
  }

  public void setMessage(String message) {
    this.message = message;
  }
}

Example2EventClass

Example2Event班级

public class Example2Event extends BaseEvent {

  private String message;

  public Example2Event() {}

  public String getMessage() {
    return message;
  }

  public void setMessage(String message) {
    this.message = message;
  }
}

Your EventListenerwould look like this.

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());
    }
  }
}

This will work for what you want to do.

这将适用于您想做的事情。

回答by user1589188

You can have multiple EventListener for each separate event.

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