事件发布到底是同步还是异步?监听器抛异常会怎样?泛型事件怎么匹配?启动过程中发布的事件为什么有的监听器收不到?这篇在 Spring Framework 7.0.9 上逐项验证。
--- 同步发布两个 OrderPlaced(金额 50 与 500) 1. publisher 调用 publishEvent 之前 [线程 main] 2. first(@Order(1)) 收到 A1 [线程 main] 3. second(@Order(2)) 收到 A1 [线程 main] 4. onEvt 收到 由监听器的返回值发布:A1 [线程 main] 5. publisher 的 publishEvent 返回了 [线程 main] 6. first(@Order(1)) 收到 A2 [线程 main] 7. second(@Order(2)) 收到 A2 [线程 main] 8. big(condition amount>100) 收到 A2 金额 500 [线程 main] 9. onEvt 收到 由监听器的返回值发布:A2 [线程 main] 10. publisher 的 publishEvent 返回了 [线程 main] --- 泛型事件:普通的 Box<String> 与 Box<Integer>(类型实现 ResolvableTypeProvider 之前) 1. (以上两个 Box 事件发布完,上面没有任何 Box 监听器被调用的记录就是没有被调用) [线程 main] --- 泛型事件:实现了 ResolvableTypeProvider 的 BoxR<String> 与 BoxR<Integer> 1. Box<String> 的监听器收到 字符串 [线程 main] 2. BoxR<String> 的监听器收到 字符串 [线程 main] 3. BoxR<Integer> 的监听器收到 42 [线程 main] 4. Box<Integer> 的监听器收到 42 [线程 main]
监听器在发布者线程里依次执行,@Order 排序,返回值被当作新事件发布,condition 用 SpEL 过滤。
--- 同步监听器抛异常 1. bad(@Order(1)) 抛异常 [线程 main] 2. publishEvent 抛给了发布者:IllegalStateException: 监听器失败 [线程 main]
同步事件里监听器抛异常,后面的监听器跳过,异常抛给发布者。
--- 多播器配了线程池(SimpleApplicationEventMulticaster.setTaskExecutor)与 ErrorHandler 1. publishEvent 返回,用了 0 ms [线程 main] 2. 第二个 publishEvent 返回 [线程 main] 3. bad(@Order(1)) 抛异常 [线程 event-pool] 4. ErrorHandler 收到异常:监听器失败 [线程 event-pool] 5. after(@Order(2)) 收到 [线程 event-pool] 6. Slow 监听器处理完 B1 [线程 event-pool]
给多播器配线程池后发布者立刻返回,异常交给 ErrorHandler。
--- 在 Early 的 @PostConstruct 里发布事件(此时容器还在 refresh 的单例创建阶段) 1. ApplicationListener 类型的 Bean 收到 Early.@PostConstruct 里发布 [线程 main] 2. Early.@PostConstruct 发布完毕 [线程 main]
@EventListener 方法在单例创建完之后才注册,更早发布的事件它收不到。
--- 内置事件 1. ContextRefreshedEvent [线程 main] 2. ContextStartedEvent [线程 main] 3. ContextStoppedEvent [线程 main] 4. ContextClosedEvent [线程 main]
refresh、start、stop、close 各发一个对应的 Context 事件。