前言
Spring声明式事务是基于Spring AOP实现的,如果对Spring AOP不太了解,可以先了解一下Spring AOP。
事务约定
对于声明式事务,时使用@Transactional注解进行标注的。这个标注可以标注在类或者方法上,当它标注在类上时,代表这个类所有公共(public)非静态的方法都将启用事务功能。
在@Transactional中,还允许配置多种配置,如:事务的传播行为、隔离级别、超时时间等。
Spring织入约定配置进行切入
我们所配置的配置项,是在Spring IoC在加载时就会将这些配置信息解析出来,然后把这些信息存储到事务定义器(TransactionDefinition接口的实现类)中,边切记录哪些类或者方法需要启动事务功能,采取什么策略去执行事务。
当Spring的上下文开始调用被@Transactional标注的类或者方法时,Spring就会产生AOP的功能。当它启动事务时,就会根据食物定义其内的配置去设置事务,首先是根据传播行为去确定事务的策略,之后是隔离界别,超时时间等内容,这些设置事务并不需要开发者完成,而是Spring事务拦截器根据@Transactional配置的内容去完成。
这里需要注意,@Transactional标注允许标注在类或者方法上,但是官方团队推荐放在实现类上,因为放在接口上将使得类基于口的代理它才会生效。
@Transactional配置
@Transactional源码如下:
package org.springframework.transaction.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import org.springframework.transaction.TransactionDefinition;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
/**
* 通过bean name指定事务管理器
*/
@AliasFor("transactionManager")
String value() default "";
/**
* 设置事务管理器事务的bean name
*/
@AliasFor("value")
String transactionManager() default "";
/**
* 指定传播行为,默认为REQUIRED 即沿用当前事务
*/
Propagation propagation() default Propagation.REQUIRED;
/**
* 指定隔离级别,默认为DEFAULT
*/
Isolation isolation() default Isolation.DEFAULT;
/**
* 设置超时时间(s)
*/
int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
/**
* 设置是否只读
*/
boolean readOnly() default false;
/**
* 方法发生异常时回滚,默认为所有异常全部回滚
*/
Class<? extends Throwable>[] rollbackFor() default {};
/**
* 方法发生指定异常名称是回滚,默认为所有异常全部回滚
*/
String[] rollbackForClassName() default {};
/**
* 方法发生指定异常时不回滚,默认所有异常全部回滚
*/
Class<? extends Throwable>[] noRollbackFor() default {};
/**
* 方法发生指定异常名称时不会滚,默认所有异常全部回滚
*/
String[] noRollbackForClassName() default {};
}
事务回滚的异常配置
①Spring的AOP即声明式事务管理默认是针对unchecked exception(RuntimeException.class)回滚,既默认只对RuntimeException()异常及其子类进行事务回滚;checked Exception(Exception.class)类型的异常不会回滚。
②刚才我们说过,Spring的事务开始于上下文开始调用@Transactional时,被注解标注的类业务方法执行完毕后执行提交或者回滚操作,而决定性因素为业务方法执行过程中是否抛出RuntimeException。如果抛出RuntimeException 并在你的业务方法中没有catch到的话,事务会回滚。
解决方法:
①显式的抛出RuntimeException异常。
②使用硬编码的方式对事务做显式的回滚。
隔离级别和传播行为配置
由于这两个属性设计数据库的特性使用,将在下一篇进行介绍。