声明式事务测试 :Spring注解笔记系列(一)
一、序言
1、为何写?
好记性不如烂笔头。
2、写来何用?
温故而知新,你懂得。
3、有谁看?
本系列笔记可作为阅读《Think In Java》辅助理解,人不可止步,圈地自封。
二、环境搭建
(1) 导入相关依赖(数据源、数据库驱动、Spring-jdbc模块)
(2) 配置数据源,JdbcTemplate(Spring提供的简化数据库操作工具)操作数据
(3) 给方法加上标注@Transactional 表示当前方法是一个事务方法
(4) @EnableTransactionManagement 开启基于注解的事务管理功能
(5) 配置事务管理器来控制事务
三、@Transactional
(1) 方法加上该注解则说明:表示当前方法是一个事务方法
四、@EnableTransactionManagement
(1) 开启基于注解的事务管理功能
(2) 原理
EnableTransactionManagement使用Import导入了TransactionManagementConfigurationSelector(继承的是ImportSelector)类,给容器中导入两个组件
A、使用selectImports(AdviceMode adviceMode)方法(AdviceMode就是该注解里定义的adviceMode属性且默认就是proxy)判断如果是PROXY,则返回String数组(AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()),如果是AspectJ则返回String数组
(TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME)
B、AutoProxyRegistrar其实就是给容器中注册Bean的(ImportBeanDefinitionRegistrar),调用ImportBeanDefinitionRegistrar(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) 给容器中注册Bean
1、判断如果是proxy,则使用AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);,并且设置了proxyTargetClass,
则会Object proxyTargetClass = candidate.get("proxyTargetClass");,其中proxyTargetClass就是该注解中定义的值(如果它为true,但是默认为false)
1.1、proxy且不等于true,调用registerAutoProxyCreatorIfNecessary(registry)。首先创建一个自动代理创建器(registerAutoProxyCreatorIfNecessary) 创建器会调用如需创建器(registerAutoProxyCreatorIfNecessary(registry, null)),如需创建器会调用需要器(registerOrEscalateApcAsRequired()), 需要器会创建一个组件(InfrastructureAdvisorAutoProxyCreator) 给容器中注册一个组件InfrastructureAdvisorAutoProxyCreator(后置处理器)
1.2、InfrastructureAdvisorAutoProxyCreator利用后置处理器机制在对象创建之后,返回一个代理对象(其中有增强器),代理对象执行方法利用拦截器链进行调用
C、ProxyTransactionManagementConfiguration作用
1、给容器中注册事务增强器
1.1、事务增强器要用事务注解的信息:AnnotationTransactionAttributeSource解析事务注解
1.2、事务拦截器:TransactionInterceptor保存了事务属性的信息,事务管理器(该类为方法拦截器)
方法拦截器:比如容器中有一个代理对象,代理对象要执行目标方法,方法拦截器就会进行工作
1.3、AOP中四个通知方法最终都被整合成事务增强器,增强器变为MethodInterceptor
2、MethodInterceptor如何工作
2.1、在目标执行的时候,因为是代理对象在执行,由于代理对象会执行拦截器链(MethodInterceptor)
2.2、事务拦截器:先获取事务相关的一些属性,再来获取PlateformTransactionManager,如果事先没有添加任何指定TransactionManager,最终会从容器中按照类型获取一个PlateformTransactionManager
2.3、目标方法先执行,如果异常,获取到事务管理器,并利用其进行回滚。如果正常,利用事务管理器提交事务