呵呵 最近有一些使用 Spring 本身提供的 Event 机制的一些东西
呵呵 因此 翻了一下 对应的代码, 稍微跟了一下, 这里整理一下 相关的收货
单元测试如下
/**
* MySpringEventTest
*
* @author Jerry.X.He
* @version 1.0
* @date 2020-06-14 10:21
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class MySpringEventTest extends BaseServiceTest {
@Autowired
private ApplicationContext applicationContext;
// ----------------------------------------------- 测试 curd -------------------------------------------------
@Test
public void test01PublishEvent() {
MyEvent event = new MyEvent(this, "context");
applicationContext.publishEvent(event);
}
}
EventListener 如下
/**
* EventListenerService
*
* @author Jerry.X.He <[email protected]>
* @version 1.0
* @date 2020-06-14 11:20
*/
@Service
public class EventListenerService {
@EventListener
public void listener01(MyEvent event) {
System.out.println("listener01 : " + event.getContext());
}
@Async
@EventListener
public void listener02(MyEvent event) {
System.out.println("listener02 : " + event.getContext());
}
@Async
@EventListener
public void listener03(MyEvent event) {
System.out.println("listener03 : " + event.getContext());
}
}
MyEvent 如下
@Data
public class MyEvent extends ApplicationEvent {
// context
private Object context;
public MyEvent(Object source, Object context) {
super(source);
this.context = context;
}
}
各个 EventListener 处理事件的时候的上下文如下
测试结果如下
我们来到 ApplicationEventMulticaster 广播事件的地方, 查询一下 ApplicationListener, 得到了我们 EventListenerService 里面注册的 三个 listener(封装的是ApplicationListenerMethodAdapter)
那么 spring 是怎么查询 applicationListener 的呢, 以及 ApplicationListenerMethodAdapter 是 spring 多久封装的呢?
1. spring 是怎么查询 applicationListener ?
ApplicationListenerMethodAdapter 中判断是否支持给定的事件的逻辑如下, 是否类型兼容
2. ApplicationListenerMethodAdapter 是 spring 多久封装的呢?
在 EventListenerService 的后置处理中, 有一个 EventListenerMethodProcessor, 来动态创建 这些 EventListener 对应的 adapter
listener01 得调用关系如下
从图中可以看出, 处理 listener01 对应的 ApplicationListenerMethodAdapter 处理业务的时候, 直接反射调用的 EventListenerService.listener01, 所以 外层单元测试 "applicationContext.publishEvent", 需要等待 EventListenerService.listener01 执行完成
我们再来看一下 listener02, listener03
由 ApplicationListenerMethodAdapter 来调用给定的 Service 的给定的方法的时候, 由于有 @Async 包了一层, 因此 多了一个 AsyncExecutionInterceptor 拦截处理了一下(配置注解 @EnableAsync)
他的处理 就是吧业务封装成了一个 Callable, 然后 交给 executor 去执行, 直接返回
因为 AsyncTaskExecutor 的处理是异步处理业务, 所以listener02, listener03 是异步的
另外就是 我们看一下 这里的 SimpleAsyncTaskExecutor 的执行任务的情况
单独创建了一个线程 来执行给定的 task
线程的名字 是一个统一的前缀 + 一个累增的索引
所以 最上面看到的 listener02 的执行线程是 SimpleAsyncTaskExecutor-1, listener03 的执行线程是 SimpleAsyncTaskExecutor-2
查询到 ProxyAsyncConfiguration
从 spring boot 的启动类 Application 上面扫描到了 @EnableAsync, 然后 @EnableAsync 上面有一个 @Import
然后 AsyncConfigurationSelector 的 selectImports 拿到了 上面的图中的 ProxyAsyncConfiguration
然后容器初始化阶段, 注册 BeanPostProcessor 的时候, 实例化了 AsyncAnnotationBeanPostProcessor 这个 bean
AsyncAnnotationBeanPostProcessor 实现了 AbstractBeanFactoryAwareAdvisingPostProcessor, 设置 beanFactory 的时候 创建了 切点, advice 等等, 初始化 pointcut, advice 的地方
完