Spring框架自带了事件监听机制,可以轻松实现观察者模式。在Spring / Spring Boot框架中内置了许多事件,同时开发者也可基于这些自定义发布应用程序事件。其中主要涉及以下几个核心类与接口。
1.ApplicationEvent应用程序事件
ApplicationEvent应用程序事件是一个抽象类,相当于观察者模式中的观察目标。ApplicationEvent源码如下:
package org.springframework.context;
import java.time.Clock;
import java.util.EventObject;
public abstract class ApplicationEvent extends EventObject {
private static final long serialVersionUID = 7099057708183571937L;
private final long timestamp;
public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}
public ApplicationEvent(Object source, Clock clock) {
super(source);
this.timestamp = clock.millis();
}
public final long getTimestamp() {
return this.timestamp;
}
}
ApplicationEvent继承自java.util.EventObject事件对象类,Spring框架中所有事件都继承自ApplicationEvent抽象类,是所有事件的父类。
ApplicationEvent主要的核心是构造函数,它可以初始化一个source事件关联对象,以便在事件监听器中获取并通知更新。
2.ApplicationListener应用程序事件监听器
ApplicationListener应用程序事件监听器是一个接口,相当于观察者模式中的观察者。ApplicationListener源码如下:
package org.springframework.context; import java.util.EventListener; import java.util.function.Consumer; @FunctionalInterface public interface ApplicationListenerextends EventListener { void onApplicationEvent(E event); static ApplicationListener > forPayload(Consumer consumer) { return (event) -> { consumer.accept(event.getPayload()); }; } }
ApplicationListener继承自java.util.EventListener事件监听接口,ApplicationListener接口中只定义了一个void onApplicationEvent(E event)方法。当指定监听的事件被发布后就会被触发执行,可以通过event获取事件中的关联对象。
3.ApplicationEventPublisher应用事件发布者
ApplicationEventPublisher应用程序事件发布接口,封装了事件发布的基础功能。ApplicationEventPublisher 接口源码如下:
package org.springframework.context;
@FunctionalInterface
public interface ApplicationEventPublisher {
default void publishEvent(ApplicationEvent event) {
this.publishEvent((Object)event);
}
void publishEvent(Object event);
}
ApplicationEventPublisher中定义了一个默认的接口方法和和普通接口方法,普通接口方法需要由具体子类容器实现。
4.ApplicationContext应用程序上下文
ApplicationContext是Spring中的核心容器之一。ApplicationContext接口继承了ApplicationEventPublisher接口,所以可以使用ApplicationContext接口来发布事件。
以上所说的Spring事件监听发布,通过ApplicationEventPublisher或者ApplicationContext容器发布事件,使用ApplicationEvent关联事件对象。然后ApplicationListener监听该事件。当事件发布后,监听器就会监听到事件的发布,并获取到事件关联对象。
5.Spring观察者模式实战
首先创建一个Spring Boot工程。然后创建事件实体:
public class EventBO {
private String name;
public EventBO(){}
public EventBO(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "EventBO{" +
"name='" + name + ''' +
'}';
}
}
创建应用事件:
public class TestApplicationEvent extends ApplicationEvent {
public TestApplicationEvent(EventBO eventBO) {
super(eventBO);
}
}
创建事件监听器:
@Component public class TestApplicationListener implements ApplicationListener{ @Override public void onApplicationEvent(TestApplicationEvent event) { EventBO source = (EventBO) event.getSource(); System.out.println("Hello " + source.getName() + " this is Spring Application Event!"); } }
创建应用上下文:
@Component
public class ApplicationContextHolder implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (ApplicationContextHolder.applicationContext == null) {
ApplicationContextHolder.applicationContext = applicationContext;
}
}
public static void publishEvent(T applicationEvent) {
applicationContext.publishEvent(applicationEvent);
}
}
在Controller中声明一个接口用于手动触发事件:
@RestController
public class HelloWorldController {
@GetMapping("event/{name}")
public void event(@PathVariable("name") String name) {
ApplicationContextHolder.publishEvent(new TestApplicationEvent(new EventBO(name)));
}
}
启动工程后请求接口http://127.0.0.1:9096/event/kapcb,控制台输出如下:
Hello kapcb this is Spring Application Event!
利用Spring中的事件监听机制可以轻松实现观察者模式,观察目标也不需要维护观察者列表。相当于发布 - 订阅模式。两者之间是完全解耦的,但是每个观察者都需要在Spring中创建一个Bean。



