spring中的事件监听机制是运用观察者模式来实现
-
观察者模式的优点有:
1、观察者和被观察者之间低耦合,代码比较好维护
2、被观察者和观察者之间是一对多Q的关系(当然也可以一对一),当被观察者状态改变的时候,多个观察者能同时进行处理,能实现广播通讯
-
观察者模式Q有两种角色:
1、Subject目标角色:接收外界的状态变化,向观察者发送通知(广播通知)
2、Observer观察者角色:观察Subject状态变化,触发具体操作罗辑
所以说subject和observer之间是一对多的关系
事件驱动模型三大要素:
- 事件(Event Object) :用户交互行为产生的一种效果 (鼠标事件、键盘事件、窗口事件)
- 事件源(Event Source) :触发事件的源头,不同的事件源会触发不同的事件
- 事件监听器(Event lisrener) :负责监听事件源发出的各种事件
事件生产者:发布事件、触发事件。
- 实现已经封装好的ApplicationEventPublisherAware接口
@Component
public class EventService implements ApplicationEventPublisherAware {
public ApplicationEventPublisher applicationEventPublisher;
@Override
public void setApplicationEventPublisher(@NotNull ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
//触发事件,也可以添加注解@Async进行异步处理
@Async
public CompletableFuture<Boolean> doEvent(EventObj o) {
applicationEventPublisher.publishEvent(o);
return CompletableFuture.completedFuture(Boolean.TRUE);
}
}
- 也可以直接进行发布
@SpringBootTest
public class PubsubTest {
@Autowired
private ApplicationEventPublisher publisher;
Message message = Message.builder()
.key("123")
.msgId(11111)
.build();
@Test
void testProducer(){
System.out.println("执行业务代码...");
publisher.publishEvent(new MessageProducerEvent(message));
}
}
事件主体
- 承载事件主体内容的类需要继承ApplicationEvent后,通过其构造方法设置事件主体所携带的事件内容或者说是发布物类型,一个主体可以承载多个事件主体内容
/**
* 事件主体
*/
public class EventObj extends ApplicationEvent {
private static final long serialVersionUID = -3917128390492677860L;
/**
*事件内容一
*/
public EventObj(EventText source) {
super(source);
}
/**
*事件内容二
*/
public EventObj(EventSon source) {
super(source);
}
}
- 或者增加泛型扩展适配
/**
* 事件主体
*/
public class EventObj<T> extends ApplicationEvent {
private static final long serialVersionUID = -3917128390492677860L;
public EventObj(T source) {
super(source);
}
}
事件内容
事件内容,其属性就是事件发生的内容数据
@Data
public class EventSon {
private String eventValue;
public EventSon(String eventValue) {
this.eventValue = eventValue;
}
}
事件监听者(订阅者)
事件响应者一般有两种实现方式,一种是实现ApplicationEvevListener接口,另一种是使用注解@EventListener
- 实现ApplicationEvevListener接口
- 可以使用泛型也可以直接用自己定义的事件主体
/** * 监听器组件 */ @Component public class EventLinstener <T extends ApplicationEvent> implements ApplicationListener<T> { @Override public void onApplicationEvent(T event) { //响应事件处理的业务代码 } }
- 使用注解@EventListener
- value:监听的事件主体
- id:标识,多个监听器顺序执行
- condition:自定义处理,例如:condition = “myEventPredicate.test(#obj)”
/** * 监听器组件 */ @Component public class EventLinstener { /** * 注册监听器1内容 * * @return */ @EventListener public Boolean eventListener0(EventObj<EventSon> obj) { System.out.println("零监听到事件:" + obj.getSource()); return Boolean.TRUE; } /** * 注册监听器1内容 * * @return */ @EventListener(value = EventObj.class) public Boolean eventListener1(EventObj<EventSon> obj) { System.out.println("一监听到事件:" + obj.getSource()); return Boolean.TRUE; } /** * 注册监听器2内容 * * @return */ @EventListener(id = "eventObj2",value = EventObj.class) public Boolean eventListener2(EventObj<EventText> obj) { System.out.println("二监听到事件:" + obj.getSource()); return Boolean.TRUE; } /** * 注册监听器3内容,自定义监听器匹配机制 * * @return */ @EventListener(id = "eventObj3",value = EventObj.class,condition = "myEventPredicate.test(#obj)") public Boolean eventListener3(EventObj obj) { System.out.println("三监听到事件:" + obj.getSource()); return Boolean.TRUE; } /** * 注册监听器4内容,自定义监听器匹配机制 * * @return */ @EventListener(id = "eventObj4",value = EventObj.class,condition = "myEventPredicate.test(#obj)") public Boolean eventListener3(EventObj obj) { System.out.println("四监听到事件:" + obj.getSource()); return Boolean.TRUE; } }
- 由于多个监听器可以监听一个事件,所以可以自定义的监听器匹配机制
/** * 可以增加断言,来判断当事件发生时,监听器是否会触发 */ @Component public class MyEventPredicate <T> implements Predicate<EventObj<T>> { @Override public boolean test(EventObj<T> eventObj) { //增加判断的逻辑,决定一个事件由哪一个监听器执行 return false; } } ------------------ /** * 注册监听器3内容,自定义监听器匹配机制 * * @return */ @EventListener(id = "eventObj3",value = EventObj.class,condition = "myEventPredicate.test(#obj)") public Boolean eventListener3(EventObj obj) { System.out.println("三监听到事件:" + obj.getSource()); return Boolean.TRUE; } /** * 注册监听器4内容,自定义监听器匹配机制 * * @return */ @EventListener(id = "eventObj4",value = EventObj.class,condition = "myEventPredicate.test(#obj)") public Boolean eventListener3(EventObj obj) { System.out.println("四监听到事件:" + obj.getSource()); return Boolean.TRUE; }
配置监听器异步执行
- 创建事件广播配置为异步
/**
* 配置所有的监听器异步执行
*/
@Configuration
public class ApplicationEventAsyncConfig {
@Resource
private ThreadPoolTaskExecutor myExecutor;
@Bean
public ApplicationEventMulticaster applicationEventMulticaster() {
//创建一个事件广播器
SimpleApplicationEventMulticaster result = new SimpleApplicationEventMulticaster();
//设置异步执行器,来完成异步执行监听事件这样会导致所有的监听器都异步执行
result.setTaskExecutor(myExecutor);
return result;
}
}
- 配置线程池
/** * 异步的线程池 */ @Configuration publicclass ThreadPoolTaskConfig { @Bean("myExecutor") public Executor taskExecutor() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); //设置线程池参数信息 taskExecutor.setCorePoolSize(8); taskExecutor.setMaxPoolSize(20); taskExecutor.setQueueCapacity(50); taskExecutor.setKeepAliveSeconds(60); taskExecutor.setThreadNamePrefix("eventHandle--"); taskExecutor.setWaitForTasksToCompleteOnShutdown(true); //设置线程池中任务的等待时间,如果超过这个时候还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是阻塞住。 taskExecutor.setAwaitTerminationSeconds(60); //修改拒绝策略为使用当前线程执行 taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); //初始化线程池 taskExecutor.initialize(); return taskExecutor; } }