zoukankan      html  css  js  c++  java
  • Spring注解驱动-注解事务的源码分析

    Spring注解驱动,注解事务的源码分析。

    @EnableTransactionManagent通过@Import(TransactionManagementConfigurationSelector.class)其selectImports(AdviceMode)方法判断是PROXY还是ASPECTJ(@EnableTransactionManagent默认参数adviceMode=PROXY),
    是PROXY,所以导入AutoProxyRegistrar和ProxyTransactionManagementConfiguration组件。
    其中AutoProxyRegistrar给容器中注册一个InfrastructureAdvisorAutoProxyCreator组件,它是一个后置处理器,在创建对象以后保证对象返回代理对象(会持有增强器),跟AOP的AnnotationAwareAspectJAutoProxyCreator作用类似。
    而ProxyTransactionManagementConfiguration是一个@Configuration类,导入了事务增强器的bean,它用用到事务注解信息,因此事务注解信息解析bean也要注入AnnotationTransactionAttributeSource(parseTransactionAnnotation方法)。
    还注册事务拦截器bean即TransactionInterceptor,保存事务属性信息和事务管理器,它是MethodInterceptor,在AOP那部分讲到过MethodInterceptor构成拦截器链,拦截目标方法。
    TransactionInterceptor的invoke方法调用invokeWithInTransaction,该方法先获取事务属性,TransactionAttribute txAttr,再获取事务管理器PlatformTransactionManager tm,然后创建事务createTransactionIfNessary,
    然后在try...Catch调用invocation.proceedWithInvocation方法,如果抛异常,执行completeTransactionAfterThrowing,它拿到事务管理器执行rollback回滚事务。拿事务管理器一般没有,从容器中获取PlatformTransactionManager,
    所以前面讲到要自己注册@Bean,注册PlatformTransactionManager,且实际注册的DataSourceTransactionManager。而如果执行成功,就执行commitTransactionAfterReturning方法提交事务,它是拿到事务管理器执行commit方法。
    这部分invokeWithInTransaction是在TransactionAspectJSupport类中。

    其次学习BeanFactoryPostProcessor接口,是在加载所有BeanDefinition之后但未初始化时执行。而BeanPostProcessor是在init-method方法前后执行。在刷新容器的refresh方法中的invokeBeanFactoryPostProcessors方法中,
    拿到所有的BeanFactoryPostProcessors,然后按PriorityOrdered接口排序分类,再按Ordered排序分类,最后才是普通的。也会分别按着3种分类去循环列表,执行每一个BeanFactoryPostProcessor的postProcessBeanFactory方法。

    另一个接口BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor(优先于BeanFactoryPostProcessor执行,在所有beanDefinition将要加载还未创建实例时,执行,用于向容器中额外增加组件),
    多了个方法postProcessorBeanDefinitionRegistry(BeanDefinitionRegistry)(这里可以在方法里拿BeanDefinitionRegistry.registerBeanDefinition一个beanDefinition,
    可以new RootBeanDefinition或BeanDefinitionBuilder.rootBeanDefinition().getDefinition),它的执行流程是在refresh方法中执行invokeBeanFactoryPostProcessors中先执行invokeBeanDefinitonRegistryPostProcessors,执行所有BeanDefinitionRegistryPostProcessor的
    postProcessorBeanDefinitionRegistry方法,再执行所有BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法(这一步注意),之后再执行所有BeanFactoryPostProcessor的postProcessBeanFactory方法。

    事件接口ApplicationListener,监听ApplicationEvent及其子事件。监听器使用步骤,1写一个监听器监听某个事件,2把监听器加到容器,3在容器中发布事件。
    容器的刷新完成(所有bean都完全创建)发布ContextRefreshedEvent事件,而容器close的时候发布ContextClosedEvent事件。发布事件使用applicationContext.publishEvent方法。
    具体是在refresh里面initApplicationEventMulticaster方法从容器中拿不到事件派发器(多播器),就new创建一个SimpleApplicationEventMulticaster放到容器中,下一步registerListeners注册所有监听器到派发器,然后在在finishRefresh中,
    获取派发器,获取所有监听器,遍历回调OnApplicationEvent,当然这里先获取线程池,有线程池就放到线程池里异步调用,没有就同步调用。线程池TaskExecutor接口有同步和异步的实现,分别是SyncTaskExecutor类和AsyncTaskExecutor接口。

    另一种方式是在任意bean的任意方法添加@EventListener(class=事件类型),然后方法的参数就是事件类型的对象,这样子也可以监听。原理是可以看@EventListener的注释,说是用EventListenerMethodProcessor来解析这个注解,
    而EventListenerMethodProcessor实现了SmartInitializingSingleton接口,有一个afterSingletonsInstantiated方法,类似于ContextRefreshedEvent的作用,它在refresh方法的finishBeanFactoryInitialization(初始化剩余的bean)方法中,
    先遍历所有的beanDefinition并getBean来创建好bean放到容器,也就是所有的bean都初始化好了,然后再遍历所有的bean执行判断是否实现了SmartInitializingSingleton接口,是就调用afterSingletonsInstantiated方法,所以会处理@EventListener注解。

  • 相关阅读:
    数据库维护单数据修改(入库单月份更改)
    Git下载GitHub上的文件
    水晶报表的步骤
    html表格及列表
    html中的a标签
    了解html标签
    常见编码方式(码表)
    了解html
    Odoo官方翻译网站
    postgresql性能的几个重要参数
  • 原文地址:https://www.cnblogs.com/kibana/p/15399594.html
Copyright © 2011-2022 走看看