58 简单了解 Spring 的 ApplicationEvent

前言

呵呵 最近有一些使用 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 处理事件的时候的上下文如下 

58 简单了解 Spring 的 ApplicationEvent_第1张图片

 

58 简单了解 Spring 的 ApplicationEvent_第2张图片

 

58 简单了解 Spring 的 ApplicationEvent_第3张图片

 

测试结果如下

58 简单了解 Spring 的 ApplicationEvent_第4张图片

 

 

@EventListener 怎么监听事件?

我们来到 ApplicationEventMulticaster 广播事件的地方, 查询一下 ApplicationListener, 得到了我们 EventListenerService 里面注册的 三个 listener(封装的是ApplicationListenerMethodAdapter)

那么 spring 是怎么查询 applicationListener 的呢, 以及 ApplicationListenerMethodAdapter 是 spring 多久封装的呢? 

 

1. spring 是怎么查询 applicationListener ?

ApplicationListenerMethodAdapter 中判断是否支持给定的事件的逻辑如下, 是否类型兼容 

58 简单了解 Spring 的 ApplicationEvent_第5张图片

 

2. ApplicationListenerMethodAdapter 是 spring 多久封装的呢?

在 EventListenerService 的后置处理中, 有一个 EventListenerMethodProcessor, 来动态创建 这些 EventListener 对应的 adapter 

 

 

同步, 异步?

listener01 得调用关系如下 

58 简单了解 Spring 的 ApplicationEvent_第6张图片

从图中可以看出, 处理 listener01 对应的 ApplicationListenerMethodAdapter 处理业务的时候, 直接反射调用的 EventListenerService.listener01, 所以 外层单元测试 "applicationContext.publishEvent", 需要等待 EventListenerService.listener01 执行完成 

 

我们再来看一下 listener02, listener03 

58 简单了解 Spring 的 ApplicationEvent_第7张图片

58 简单了解 Spring 的 ApplicationEvent_第8张图片

由 ApplicationListenerMethodAdapter 来调用给定的 Service 的给定的方法的时候, 由于有 @Async 包了一层, 因此 多了一个 AsyncExecutionInterceptor 拦截处理了一下(配置注解 @EnableAsync) 

他的处理 就是吧业务封装成了一个 Callable, 然后 交给 executor 去执行, 直接返回 

因为 AsyncTaskExecutor 的处理是异步处理业务, 所以listener02, listener03 是异步的 

 

 

另外就是 我们看一下 这里的 SimpleAsyncTaskExecutor 的执行任务的情况 

58 简单了解 Spring 的 ApplicationEvent_第9张图片

单独创建了一个线程 来执行给定的 task  

58 简单了解 Spring 的 ApplicationEvent_第10张图片

线程的名字 是一个统一的前缀 + 一个累增的索引 

所以 最上面看到的 listener02 的执行线程是 SimpleAsyncTaskExecutor-1, listener03 的执行线程是 SimpleAsyncTaskExecutor-2 

 

 

关于 @EnableAsync

查询到 ProxyAsyncConfiguration 

 

从 spring boot 的启动类 Application 上面扫描到了 @EnableAsync, 然后 @EnableAsync 上面有一个 @Import 

 

然后 AsyncConfigurationSelector 的 selectImports 拿到了 上面的图中的 ProxyAsyncConfiguration 58 简单了解 Spring 的 ApplicationEvent_第11张图片 

然后容器初始化阶段, 注册 BeanPostProcessor 的时候, 实例化了 AsyncAnnotationBeanPostProcessor 这个 bean 

 

AsyncAnnotationBeanPostProcessor 实现了 AbstractBeanFactoryAwareAdvisingPostProcessor, 设置 beanFactory 的时候 创建了 切点, advice 等等, 初始化 pointcut, advice 的地方 

 

 

完 

 

 

你可能感兴趣的:(05,问题)