0%

Spring 事件

Spring 事件

1
Event handling in the ApplicationContext is provided through the ApplicationEvent class and the ApplicationListener interface. If a bean that implements the ApplicationListener interface is deployed into the context, every time an ApplicationEvent gets published to the ApplicationContext, that bean is notified. Essentially, this is the standard Observer design pattern.

定义事件

1
2
3
4
5
6
7
8
@Getter
public class PaymentEvent extends ApplicationEvent {
private final String account;
public PaymentEvent(Object source, String account) {
super(source);
this.account = account;
}
}

定义监听

  • 实现 ApplicationListener 接口
1
2
3
4
5
6
7
8
@Component
public class CustomerEventListenerV2 implements ApplicationListener<EmailEvent> {

@Override
public void onApplicationEvent(EmailEvent event) {
// 事件处理
}
}
  • 注解@EventListener
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Component
public class CustomerEventListener {

@EventListener(classes = PaymentEvent.class)
public void processPaymentEvent(PaymentEvent event) {
// 事件处理
}

// 官方文档描述当监听多个事件时,不允许定义任何参数 但是实际测试可以定义一个参数
// The event classes that this listener handles.
// <p>If this 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 <em>not</em> declare any parameters.
@EventListener(classes = {PaymentEvent.class, EmailEvent.class})
public void processBlockedListEvent(ApplicationEvent event) {
if (event instanceof PaymentEvent) {
System.out.println("接收到事件:" + ((PaymentEvent) event).getAccount());
}

if (event instanceof EmailEvent) {
System.out.println("接收到事件:" + ((EmailEvent) event).getAddress());
}
}

}

事件的处理后返回下一个事件

1
2
3
4
5
6
7
8
9
10
@Component
@Slf4j
public class CustomerEventListenerV2 {
@EventListener(classes = SendGoodEvent.class)
public PaymentEvent onApplicationEvent(SendGoodEvent event) {
// 事件处理
log.info("订单发货:{}", event.getName());
return new PaymentEvent(event, "5000");
}
}

异步监听事件处理

实现事件异步监听只需要在监听方法上增加注解**@Async**即可.

  • If an asynchronous event listener throws an Exception, it is not propagated to the caller. See AsyncUncaughtExceptionHandler for more details.
  • 不支持事件传播
  • Asynchronous event listener methods cannot publish a subsequent event by returning a value. If you need to publish another event as the result of the processing, inject an ApplicationEventPublisher to publish the event manually.
1
2
3
4
5
@EventListener
@Async
public void processBlockedListEvent(BlockedListEvent event) {

}

事件优先级

1
2
3
4
5
@EventListener
@Order(42)
public void processBlockedListEvent(BlockedListEvent event) {
// notify appropriate parties via notificationAddress...
}

Event SpEL

这个暂时不看

新特性

As of Spring 4.2, the event infrastructure has been significantly improved and offers an annotation-based model as well as the ability to publish any arbitrary event (that is, an object that does not necessarily extend from ApplicationEvent). When such an object is published, we wrap it in an event for you.

Spring4.2 之后,可以不继承 ApplicationEvent,直接以 model 形式实现事件.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 定义事件
@Getter
public class SendGoodEvent{
private final String name;
private final long count;
public SendGoodEvent(String name, long count) {
this.name = name;
this.count = count;
}
}

// 事件监听器
@Component
@Slf4j
public class CustomerEventListenerV2 {
@EventListener(classes = SendGoodEvent.class)
public void onApplicationEvent(SendGoodEvent event) {
// 事件处理
log.info("订单发货:{}", event.getName());
}
}

// 源码
@FunctionalInterface
public interface ApplicationEventPublisher {

default void publishEvent(ApplicationEvent event) {
publishEvent((Object) event);
}
// Spring 4.2之后新增的事件发布方法
void publishEvent(Object event);

}