• 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注解。

  • 相关阅读:
    第二阶段--团队冲刺--第八天
    第二阶段--团队冲刺--第七天
    第二阶段--团队冲刺--第六天
    ShardingJdbc:Springboot集成ShardingSphere,单服务跨数据源时,简单实现事务管理
    ShardingJdbc:集成ShardingSphere后,像MasterDataTable这样不需要分库分表,该怎么实现的一个方案
    小知识:mybatisGeneratorConfig的xml 数据库连接URL报错:&符号报错 connectionURL="jdbc:mysql://localhost:3306/mcspcsales?charset=utf8mb4&useSSL=false&serverTimeZone=GMT%2B8"
    小知识:如何在idea中执行mybatis-generator,生成mapper
    小知识:idea新建项目后,希望通过actuator查询当前是否正常,发现前台画面显示whiteablepage
    小知识:windows安装mysql报错,安装mysql时提示错误: C:mysql-5.7.29-winx64in>mysqld -install MySQL Install/Remove of the Service Denied!
    小知识:nginx转发访问时,报404错误
  • 原文地址:https://www.cnblogs.com/kibana/p/15399594.html
Copyright © 2020-2023  润新知