目录
一、概述
二、分析@EventListener
2.4 EventListenerMethodProcessor
2.5 DefaultEventListenerFactory
2.6 ApplicationListenerMethodAdapter
三、分析@TransactionalEventListener
3.3 TransactionalEventListenerFactory
3.4 ApplicationListenerMethodTransactionalAdapter
1.1 @EventListener是用来标识在方法上,使得该方法可以监听事件,在事件发布时调用方法处理事件(作用与实现ApplicationListener接口的事件监听器一样,参考分析Spring-ApplicationListener监听器_Just-Today的博客-CSDN博客)。
@EventListener注解有2个属性设置了别名, 分别是value、classes,这2个属性是可用来设置监听器监听事件的类型。
要求:
1、若value()和classes()没有设置值,则标识@EventListener的方法必须有且只能有一个参数。
2、若value()或classes()设置了值,
2.1、单个Class值,则标识@EventListener的方法可以不用设置参数。若想要设置一个参数,则参数的类型一定要是Class或Class的父类或接口。
2.2、多个Class值,官方要求@EventListener的方法一定不要设置参数。若是想要设置一个参数,则参数的类型一定要是所有Class的共同父类或接口。因为在监听事件时,通过反射监听方法处理事件,事件转换成方法参数时,若类型不一致,可能会发生类型转换异常。
1.2 @TransactionalEventListener的注解上标识@EventListener注解,相当于继承了@EventListener注解的功能,并添加了新的特性。
2.1 创建AnnotationConfigApplicationContext容器对象时,在构造器中创建了一个AnnotatedBeanDefinitionReader类型的reader。
2.2 在AnnotatedBeanDefinitionReader构造器中调用了AnnotationConfigUtils.registerAnnotationConfigProcessors方法。
2.3 registerAnnotationConfigProcessors方法主要是向容器注册创建了一些组件对象。例如扫描解析配置类的ConfigurationClassPostProcessor;解析@Autowired、@Value、@Inject注解的AutowiredAnnotationBeanPostProcessor;解析@Resource注解、@PostConstruct、@PreDestroy的CommonAnnotationBeanPostProcessor等。
其中包含类型为EventListenerMethodProcessor的组件和类型为DefaultEventListenerFactory的组件也注册到容器中。
EventListenerMethodProcessor是用来解析@EventListener注解,该类实现了SmartInitializingSingleton、BeanFactoryPostProcessor接口。
2.4.1 在postProcessBeanFactory方法中,从容器中找到类型为EventListenerFactory的组件对象集合,并利用AnnotationAwareOrderComparator的sort方法进行排序,然后赋值给eventListenerFactories。
而DefaultEventListenerFactory实现了EventListenerFactory接口,在这里也会被加入到eventListenerFactories集合中。
2.4.2 容器利用preInstantiateSingletons方法创建初始化非延迟加载的单实例组件后,遍历beanNames(容器组件名称集合),调用getSingleton方法找到实现SmartInitializingSingleton接口的单实例对象,调用对象的afterSingletonsInstantiated方法。
在此时,EventListenerMethodProcessor的afterSingletonsInstantiated方法被调用。
2.4.3 EventListenerMethodProcessor的afterSingletonsInstantiated方法中调用processBean方法。
2.4.4 在processBean方法中,先根据@EventListener得到key为method,value为EventListener的annotatedMethods,annotatedMethods存储了标识@EventListener的方法和注解的相关信息。
接下来,遍历annotatedMethods的key,遍历之前存于EventListenerMethodProcessor.eventListenerFactories的EventListenerFactory对象,先通过factory的supportsMethod判断factory是否支持method。
若支持,则通过factory的createApplicationListener方法创建监听器对象。
而DefaultEventListenerFactory的createApplicationListener方法会为标识@EventListener的方法创建类型为ApplicationListenerMethodAdapter的监听器对象,然后将监听器对象加到容器的事件多播器中。
DefaultEventListenerFactory实现了EventListenerFactory接口,实现的createApplicationListener方法是为标识@EventListener的方法创建类型为ApplicationListenerMethodAdapter的事件监听器对象,method是标识@EventListener的方法。
2.6.1 在ApplicationListenerMethodAdapter构造函数中,通过调用resolveDeclaredEventTypes方法来得到监听器监听事件的类型集合。
进入resolveDeclaredEventTypes方法,标识@EventListener注解的方法若有参数,则只能有一个。
若是classes()属性有值,通过遍历classes属性得到监听器监听事件的类型集合。
若是classes()属性没有值,则标识@EventListener注解的监听方法必须有且只能有一个参数,参数的类型就是监听事件的类型。
2.6.2 ApplicationListenerMethodAdapter实现了GenericApplicationListener接口。
在多播器寻找可以监听事件的监听器时,遍历监听器集合,调用supportsEvent方法。
supportsEvent方法中,将listener监听器转换成GenericApplicationListener,然后调用GenericApplicationListener的supportsEventType方法。
ApplicationListenerMethodAdapter实现了GenericApplicationListener接口,实现的supportsEventType方法中,遍历declaredEventTypes(监听器监听事件的类型集合),
先通过isAssignableFrom方法判断eventType(发布事件的类型)是否是declaredEventType或者它的实现类(继承或实现declaredEventType)。
若是,则表示该监听器可以监听此发布事件,返回true。
若不是,则接着判断eventType是否是PayloadApplicationEvent或者它的实现类。
若是,则得到PayloadApplicationEvent的T泛型类型(也就是payload的实际类型),然后通过isAssignableFrom方法判断payloadType是否是declaredEventType或它的实现类。若是,则返回true。
最后若是集合遍历结束,还没找到可以监听发布事件的类型,则继续调用eventType.hasUnresolvableGenerics()方法继续判断。
2.6.3 后续容器发布事件时,调用ApplicationListenerMethodAdapter对象的onApplicationEvent方法,onApplicationEvent方法了调用processEvent方法。
2.6.4 在processEvent方法中,先通过resolveArguments方法得到反射监听器方法所需要的参数args。如果args为null,则shouldHandle方法会返回false,不反射监听器方法处理事件。
resolveArguments方法先根据getResolvableType方法得到监听器可以监听发布事件的事件类型,
如果返回null,则直接返回。
若不为null,继续往下进行,若监听器方法没有参数,则直接返回空数组。
如果监听器方法含有参数,继续往下,在判断中,如果declaredEventClass不是ApplicationListener的子类(监听事件的类型是普通的Object类型),且发布事件event的类型是PayloadApplicationEvent或它的子类,则判断PayloadApplicationEvent的payload属性和declaredEventClass的关系。若是payload是declaredEventClass的实现类,则返回存储payload的对象数组。
最后返回存储event的对象数组。
getResolvableType方法,先判断发布事件的类型是否是PayloadApplicationEvent或它的子类,若是,则获取payloadType(若是发布事件的类型是普通的Object类型,则容器会为Object创建PayloadApplicationEvent对象,payload属性就是普通的Object类型)。
然后遍历监听器监听事件的类型集合,先判断监听事件的类型如果不是ApplicationEvent的子类且payloadType有值、payloadType是declaredEventType(监听事件的类型)或它的实现类,则返回declaredEventType。
若event(发布事件)是eventClass(监听事件的类型)的实现类,则返回declaredEventType。
若是没找到对应的declaredEventType,则最后返回null。
2.6.3 调用doInvoke方法通过反射运行method,也就是标识@EventListener注解的方法。
2.6.4 若doInvoke方法有返回值,也就是标识@EventListener的方法有返回值时,调用handleResult方法继续发布事件。
注意:若方法有返回值,需处理好,否则容易造成一直循环发布同一事件,导致发生异常。
3.1 @TransactionalEventListener注解类上标识了@EventListener注解,说明@TransactionalEventListener拥有@EventListener注解的功能,在EventListenerMethodProcessor的afterSingletonsInstantiated方法中会被扫描出来。
3.2 通过@EnableTransactionManagement注解开启注解事务时,会向容器注册类型为ProxyTransactionManagementConfiguration的组件对象,而ProxyTransactionManagementConfiguration继承了AbstractTransactionManagementConfiguration。
AbstractTransactionManagementConfiguration通过@Bean注解向容器注册了类型为TransactionalEventListenerFactory的组件。
3.3.1 TransactionalEventListenerFactory实现了EventListenerFactory接口,实现的createApplicationListener方法会为标识@TransactionalEventListener的方法创建类型为ApplicationListenerMethodTransactionalAdapter的对象。
3.3.2 在EventListenerMethodProcessor的postProcessBeanFactory方法中,TransactionalEventListenerFactory对象也会被getBeanOfType方法扫描出来,然后通过AnnotationAwareOrderComparator排序器的sort方法排序,之前容器默认添加的DefaultEventListenerFactory对象会排到TransactionalEventListenerFactory后面,并加入到eventListenerFactories集合中。
3.3.3 在EventListenerMethodProcessor的processBean方法中,遍历eventListenerFactories时,会先遍历到类型为TransactionalEventListenerFactory的对象。
3.3.4 TransactionalEventListenerFactory通过supportsMethod方法判断是否支持method(标识@EventListener、@TransactionalEventListener的方法),
supportsMethod方法支持标识@TransactionalEventListener注解的方法。
3.3.5 若是TransactionalEventListenerFactory支持method,则通过调用TransactionalEventListenerFactory的createApplicationListener方法,创建类型为ApplicationListenerMethodTransactionalAdapter(继承ApplicationListenerMethodAdapter)的监听器对象。(若是没有开启注解事务,则DefaultEventListenerFactory会为标识@TransactionalEventListener的方法创建类型为ApplicationListenerMethodAdapter的对象)
3.4.1 容器发布事件时,调用ApplicationListenerMethodTransactionalAdapter监听器的onApplicationEvent方法。
3.4.2 先通过TransactionSynchronizationManager.isSynchronizationActive()判断当前线程是否有正在运行的事务。若是有,则通过createTransactionSynchronization方法创建TransactionSynchronizationEventAdapter对象,然后将synchronization注册到当前线程的事务中。
3.4.2.1 容器会对标识@Transactional的方法生成代理对象,运行标识@Transactional注解的方法时,通过代理对象生成拦截器链,调用TransactionInterceptor拦截器的invoke方法开启事务,运行方法。
3.4.2.2 提交事务时,最终会调用事务管理器AbstractPlatformTransactionManager的processCommit方法(详细调用可到源码查看),
在processCommit方法中,会先调用prepareForCommit(提交事务之前做一些准备工作)、triggerBeforeCommit(触发事务TransactionSynchronization的beforeCommit方法)、triggerBeforeCompletion(触发事务TransactionSynchronization的beforeCompletion方法)。
3.4.2.3 进入triggerBeforeCommit方法,调用TransactionSynchronizationUtils.triggerBeforeCommit方法。
3.4.2.4 在TransactionSynchronizationUtils.triggerBeforeCommit方法中,会遍历之前存于当前线程的事务同步TransactionSynchronization集合,调用TransactionSynchronization的beforeCommit方法,
而在之前3.4.2节中,已经将TransactionSynchronizationEventAdapter加入到当前线程的事务同步集合中,所以此时会调用TransactionSynchronizationEventAdapter的beforeCommit方法。
3.4.2.5 TransactionSynchronizationEventAdapter的beforeCommit方法,会先判断@TransactionalEventListener注解的phase值。若是phase等于BEFORE_COMMIT,则调用processEvent方法开始处理事件(参考2.6.2节)。
3.4.2.6 若成功提交事务,则会调用triggerAfterCommit方法触发TransactionSynchronization的AfterCommit方法。
而在afterCommit方法中会调用TransactionSynchronization的afterCommit方法,而之前存储的TransactionSynchronizationEventAdapter对象,没重写该方法,默认为空方法。
3.4.2.7 最终不管事务是提交或者回滚,都会调用triggerAfterCompletion方法,传入TransactionSynchronization的状态值(0表示commit提交事务 1表示rollback回滚事务 2表示unknown,可能发生系统error)。
通过调用invokeAfterCompletion方法遍历当前线程的TransactionSynchronization集合,调用TransactionSynchronization的afterCompletion方法。
TransactionSynchronizationEventAdapter的afterCompletion方法被调用。
3.4.2.8 判断phase和status发布事件,例如phase等于TransactionPhase.AFTER_COMMIT,且事务正常提交,status等于STATUS_COMMITTED(0),则通过processEvent方法处理事件。
3.4.2.9 回滚事务时,最终会调用事务管理器AbstractPlatformTransactionManager的processRollback方法(调用步骤与3.9.2节调用processCommit方法差不多,详细可到源码查看)。
3.4.3 若是当前线程不存在事务,则判断@TransactinalEventListener的fallbackExecution属性是否是true。若是true,则表示若当前线程没有正在运行事务运行,该监听器也会监听事件发布,运行processEvent方法调用方法处理事件。
3.4.4 若是当前线程不存在事务,且fallbackExecution属性为false,则不处理事件。
参考
https://www.jianshu.com/p/22b75f98ed16