Spring Transaction
- @EnableTransactionManagement
- AutoProxyRegistrar
- ProxyTransactionManagementConfiguration
-
- 给容器中注册事务增强器transactionAdvisor
- 事务拦截器transactionInterceptor
- 事务隔离级别
- 事务传播行为
@EnableTransactionManagement
利用TransactionManagementConfigurationSelector给容器中会导入组件
- AutoProxyRegistrar
- ProxyTransactionManagementConfiguration
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
//导入两个组件
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
AutoProxyRegistrar
- 给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件;
- 利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用;
ProxyTransactionManagementConfiguration
ProxyTransactionManagementConfiguration是个@Configuration
给容器中注册事务增强器transactionAdvisor
- 事务增强器要用事务注解的信息,AnnotationTransactionAttributeSource解析事务注解
事务拦截器transactionInterceptor
- TransactionInterceptor: 保存了事务属性信息,事务管理器;
-
TransactionInterceptor是一个 MethodInterceptor;
在目标方法执行的时候,执行拦截器链;
只有事务拦截器:
- 先获取事务相关的属性
-
再获取PlatformTransactionManager,如果事先没有添加指定任何transactionmanger
最终会从容器中按照类型获取一个PlatformTransactionManager;
-
执行目标方法
如果异常,获取到事务管理器,利用事务管理回滚操作;
如果正常,利用事务管理器,提交事务
事务隔离级别
@Transactional(isolation = Isolation.READ_UNCOMMITTED) 读取未提交数据(会出现脏读, 不可重复读),基本不使用
@Transactional(isolation = Isolation.READ_COMMITTED)(SQLSERVER默认) 读取已提交数据(会出现不可重复读和幻读)
@Transactional(isolation = Isolation.REPEATABLE_READ) 可重复读(会出现幻读)
@Transactional(isolation = Isolation.SERIALIZABLE) 串行化
事务传播行为
@Transactional(propagation=Propagation.REQUIRED) 如果有事务, 那么加入事务, 没有的话新建一个(默认情况)
@Transactional(propagation=Propagation.NOT_SUPPORTED) 容器不为这个方法开启事务
@Transactional(propagation=Propagation.REQUIRES_NEW) 不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
@Transactional(propagation=Propagation.MANDATORY) 必须在一个已有的事务中执行,否则抛出异常
@Transactional(propagation=Propagation.NEVER) 必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
@Transactional(propagation=Propagation.SUPPORTS) 如果其他bean调用这个方法,在其他bean中声明事务,那就用事务。如果其他bean没有声明事务,那就不用事务