持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情
一、@Transaction注解属性
| 编号 | 属性名 | 说明 |
|---|---|---|
| 1 | name | 当在配置文件中有多个 TransactionManager , 可以用该属性指定选择哪个事务管理器。 |
| 2 | propagation | 事务的传播行为,默认值为 REQUIRED。 |
| 3 | isolation | 事务的隔离度,默认值采用 DEFAULT。isolation = Isolation.READ_COMMITTED |
| 4 | timeout | 事务的超时时间,默认值为-1。如果超过该时间限制但事务还没有完成,则自动回滚事务。 |
| 5 | read-only | 指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true。 |
| 6 | rollback-for | 用于指定能够触发事务回滚的异常类型,如果有多个异常类型需要指定,各类型之间可以通过逗号分隔。 |
| 7 | no-rollback- for | 抛出 no-rollback-for 指定的异常类型,不回滚事务。 |
二、使用范例
指定回滚定义的特定的异常类型 @Transactional(rollbackFor= MyException.class)
三、作用范围
1、方法:推荐将注解使用于方法上,不过需要注意的是:该注解只能应用到 public 方法上,否则不生效。
2、类:如果这个注解使用在类上的话,表明该注解对该类中所有的 public 方法都生效。
3、接口:不推荐在接口上使用。
四、@Transactional 的使用注意事项总结
1)@Transactional 注解只有作用到 public 方法上事务才生效,不推荐在接口上使用;
2)避免同一个类中调用 @Transactional 注解的方法,这样会导致事务失效;
3)正确的设置 @Transactional 的 rollbackFor 和 propagation 属性,否则事务可能会回滚失败;
4)被 @Transactional 注解的方法所在的类必须被 Spring 管理,否则不生效;
5)底层使用的数据库必须支持事务机制,否则不生效;
6)只有当 @Transactional 注解的方法在类以外被调用的时候,Spring 事务管理才生效。
五、@Transactional事务注解原理
我们知道,@Transactional 的工作机制是基于 AOP 实现的,AOP 又是使用动态代理实现的。如果目标对象实现了接口,默认情况下会采用 JDK 的动态代理,如果目标对象没有实现了接口,会使用 CGLIB 动态代理。 createAopProxy() 方法 决定了是使用 JDK 还是 Cglib 来做动态代理,源码如下:
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
}
如果一个类或者一个类中的 public 方法上被标注@Transactional 注解的话,Spring 容器就会在启动的时候为其创建一个代理类,在调用被@Transactional 注解的 public 方法的时候,实际调用的是,TransactionInterceptor 类中的 invoke()方法。这个方法的作用就是在目标方法之前开启事务,方法执行过程中如果遇到异常的时候回滚事务,方法调用完成之后提交事务。