spring 中的事件监听机制是运用观察者模式来实现的,观察者模式的优点有:
1、观察者和被观察者之间低耦合,代码比较好维护
2、被观察者和观察者之间是一对多的关系(当然也可以一对一),当被观察者状态改变的时候,多个观察者能同时进行处理,能实现广播通讯
观察者模式有两种角色:
1、Subject 目标角色:接收外界的状态变化,向观察者发送通知(广播通知)
2、Observer 观察者角色:观察Subject状态变化,触发具体操作逻辑
所以说subject 和 observer之间是一对多的关系
现在我们用spring监听机制来实现上述图示:
observer1,observer2,observer3监听subject1的状态变化
observer3,observer4监听subject2的状态变化
可见observer3同时可以监听subject1,subject2的状态变化
Subject1:声明事件1,Object source是通信传输数据的实体
/**
* @Author yangcai
* @create 2022/6/24 15:47
*/
public class Subject1 extends ApplicationEvent {
public Subject1(Object source) {
super(source);
}
}
Subject2:声明事件2,Object source是通信传输数据的实体
/**
* @Author yangcai
* @create 2022/6/24 15:47
*/
public class Subject2 extends Subject1 {
public Subject2(Object source) {
super(source);
}
}
EventPublisher:事件发布器,给监听器发送通知,触发监听器的执行
@Component
@Slf4j
public class EventPublisher implements ApplicationEventPublisherAware {
private ApplicationEventPublisher eventPublisher;
public void publish(ApplicationEvent event) {
eventPublisher.publishEvent(event);
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.eventPublisher = applicationEventPublisher;
}
}
@Data
public class SourceEntity {
private String subjectName;
private String notifyMsg;
}
ObserverEventHandler 声明监听器及监听的事件,多个监听器可以监听一个事件
/**
* @Author yangcai
* @create 2022/6/24 15:48
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class ObserverEventHandler {
@EventListener(id="observer1",condition = "@listenerPredicate.test(#event)")
public void handle1(Subject1 event) {
SourceEntity sourceEntity = (SourceEntity)event.getSource();
log.info("--observer1---handle1-----"+sourceEntity.getSubjectName());
}
@EventListener(id="observer2",condition = "@listenerPredicate.test(#event)")
public void handle2(Subject1 event) {
SourceEntity sourceEntity = (SourceEntity)event.getSource();
log.info("--observer2---handle2-----"+sourceEntity.getSubjectName());
}
@EventListener(id="observer3")
public void handle3(Subject1 event) {
SourceEntity sourceEntity = (SourceEntity)event.getSource();
log.info("--observer3---handle3-----"+sourceEntity.getSubjectName());
}
@EventListener(id="observer4")
public void handle4(Subject2 event) {
SourceEntity sourceEntity = (SourceEntity)event.getSource();
log.info("--observer4---handle4-----"+sourceEntity.getSubjectName());
}
}
监听器监听事件的条件匹配器,可以根据通信实体中的数据,当事件被发布时,来进行判断当前监听器是否会触发执行
/**
* @Author yangcai
* @create 2022/6/28 16:20
*/
@Component
public class ListenerPredicate implements Predicate<ApplicationEvent> {
@Override
public boolean test(ApplicationEvent event) {
SourceEntity sourceEntity = (SourceEntity)event.getSource();
if(event instanceof Subject2 && "subject2".equals(sourceEntity.getSubjectName())){
return false;
}
return true;
}
}
测试subject1:
@SpringBootApplication
public class Stu1Application {
public static void main(String[] args) throws InterruptedException {
ApplicationContext ac = SpringApplication.run(Stu1Application.class, args);
SubjectPublisher eventPublisher = ac.getBean(SubjectPublisher.class);
SourceEntity sourceEntity = new SourceEntity();
sourceEntity.setSubjectName("subject1");
eventPublisher.publish(new Subject1(sourceEntity));
}
}
结果:
测试subject2:
@SpringBootApplication
public class Stu1Application {
public static void main(String[] args) throws InterruptedException {
ApplicationContext ac = SpringApplication.run(Stu1Application.class, args);
SubjectPublisher eventPublisher = ac.getBean(SubjectPublisher.class);
SourceEntity sourceEntity = new SourceEntity();
sourceEntity.setSubjectName("subject2");
eventPublisher.publish(new Subject2(sourceEntity));
}
}
结果:
配置监听器异步执行:需要新增两个配置文件
/**
* @Author yangcai
* @create 2022/6/24 15:57
*/
@Configuration
public class ApplicationEventAsyncConfig {
@Resource
private ThreadPoolTaskExecutor myExecutor;
@Bean
public ApplicationEventMulticaster applicationEventMulticaster() { //@1
//创建一个事件广播器
SimpleApplicationEventMulticaster result = new SimpleApplicationEventMulticaster();
//设置异步执行器,来完成异步执行监听事件这样会导致所有的监听器都异步执行
result.setTaskExecutor(myExecutor);
return result;
}
}
@Configuration
public class ThreadPoolConfig {
@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;
}
}