? spring提供了三大接口来实现事务的控制
PlatformTransactionManager
此接口定义了事务的基本操作,因为此类是一个接口,所以我们创建事务对象,需要用其实现类DataSourceTransactionManager
方法 | 说明 |
---|---|
DataSourceTransactionManager(DataSource dataSource) | 构造方法,用于创建事务对象 |
void commit(TransactionStatus status) | 提交事务,需要提供事务的状态对象作为参数 |
void rollback(TransactionStatus status) | 回归事务,需要提供事务的状态对象作为参数 |
TransactionStatus getTransaction(TransactionDefinition definition) | 获取事务的状态对象 |
TransactionDefinition
此接口定义了事务的基本信息,包括事务的隔离级别,事务的名称,超时时间等等;要注意的是如果要创建事务定义对象,需要使用其实现类DefaultTransactionDefinition
方法 | 说明 |
---|---|
DefaultTransactionDefinition() | 构造方法,创建事务定义对象 |
String getName() | 获取事务定义名称 |
boolean isReadOnly() | 获取事务的读写属性 |
int getIsolationLevel() | 获取事务隔离级别 |
TransactionStatus
事务状态对象,此接口定义了事务在执行过程中的信息,这个接口的实现类对象通过事务管理获取PlatformTransactionManager
方法 | 说明 |
---|---|
PlatformTransactionManager . getTransaction(TransactionDefinition definition) | 获取事务状态对象 |
boolean isNewTransaction() | 获取事务是否处于新开启事务状态 |
boolean isCompleted() | 获取事务是否处于回滚状态 |
void setRollbackOnly() | 设置事务处于回滚状态 |
? 模拟转账业务,也是采用AOP的方法,为原始方法增强业务功能。
原始方法
/**
*
* @param outName 出账用户名
* @param inName 入账用户名
* @param money 转账金额
*/
public void transfer(String outName, String inName, Double money) {
//执行业务
accountDao.inMoney(outName, money);
//模拟报错
int i = 1 / 0;
accountDao.outMoney(inName, money);
}
环绕通知
public class TxAdvice {
//数据源
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
/**
* 环绕通知
*/
public Object transactionManager(ProceedingJoinPoint pjp) throws Throwable {
//创建事务
PlatformTransactionManager dt = new DataSourceTransactionManager(dataSource);
//创建事务定义对象
TransactionDefinition td = new DefaultTransactionDefinition();
//获取事务状态
TransactionStatus ts = dt.getTransaction(td);
//调用原始方法
Object result = pjp.proceed(pjp.getArgs());
//提交事务
dt.commit(ts);
return result;
}
}
配置aop
<!--配置事务bean-->
<bean id="txAdvice" class="com.itheima.aop.TxAdvice">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--配置aop-->
<aop:config>
<!--配置切入点-->
<aop:pointcut id="pt" expression="execution(* *.*.transfer(..))"/>
<!--配置切面,整合切入点和通知-->
<aop:aspect ref="txAdvice">
<!--环绕通知-->
<aop:around method="transactionManager" pointcut-ref="pt"/>
</aop:aspect>
</aop:config>
说明
Spring 框架本身已经充分考虑了对事物的支持,所以我们完全不必像之前一样自定义类来实现对事物的控制。Spring 已经抽象了一整套的事务机制,而作为开发人员根本不必了解底层的事务 API,所以我们可以采用 Spring 提供的管理器实现类,来替换掉之前我们自己编写的事务控制工具类。
实现步骤
在配置文件中,初始化 Spring 框架提供的事务管理器的实现类。
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--引用数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
使用 Spring 提供的事务管理器类作为切面,在其中配置事务通知。
<!--配置事务通知,transaction-manager:引用事务管理器bean-->
<tx:advice id="txAdvice" transaction-manager="txManager">
<!--配置事务属性-->
<tx:attributes>
<!--配置所有方法都能读写->
<tx:method name="*" read-only="false"/>
<!--配置find开头的方法只能读-->
<tx:method name="find*" read-only="true"/>
</tx:attributes>
</tx:advice>
aop配置,整合切入点与事务通知
<!--配置aop-->
<aop:config>
<!--配置切入点,指定要拦截的方法-->
<aop:pointcut id="pt" expression="execution(* com.itheima.service..*.*(..))"/>
<!--整合切入点以及事务通知-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
</aop:config>
<tx:method>
标签的属性<tx:method
name="*"
read-only="false"
timeout="-1"
isolation="DEFAULT"
no-rollback-for=""
rollback-for=""
propagation="REQUIRED"
/>
配置步骤
在配置文件中配置组件扫描
<!--配置组件扫描器-->
<context:component-scan base-package="com.itheima"/>
在配置文件中配置事务管理器
<!--初始化事务管理器-->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--引用数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
在配置文件中开启事务注解驱动支持
<!--
开启事务注解驱动
transaction-manager:引用事务管理器bean
-->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
使用@Transactional注解
作用位置:接口类上,接口方法上。
作用:设置当前类/接口中所有方法或具体方法开启事务,并指定相关事务属性。
属性
@Transactional(
readOnly = false,
timeout = -1,
isolation = Isolation.DEFAULT,
rollbackFor = {ArithmeticException.class, IOException.class},
noRollbackFor = {},
propagation = Propagation.REQUIRES_NEW
)
一般不加参数。
使用全注解
配置步骤
编写事务管理配置类,将事务管理器存入spring容器
注意:事务管理类要依赖数据源
/**
* 配置事务管理器
*/
@Bean
public DataSourceTransactionManager getTransactionManager(@Autowired DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
在spring配置类中开启事务管理注解驱动
@Configuration
@ComponentScan("com.itheima")
@Import({JdbcConfig.class, MybatisConfig.class})
//启用事务管理注解驱动
@EnableTransactionManagement
public class SpringConfig {
}
注解解释:
@Configuration
:表示当前类是spring的配置类,当创建spring容器的时候,就使用此类来创建。@ComponentScan
:组件扫描,配置后spring在加载的时候才会根据你配置的扫描包,去包下扫描注解。@Import
:引入其他配置类,存入spring容器中,作为bean。@EnableTransactionManagement
:此注解表示启用事务管理注解驱动,只有当配置这个注解,spring才会去解析程序中使用的@Transactional
注解在程序的接口/接口方法上使用@Transactional
注解。
设置@Transactional
注解所在的当前类/接口中,所有方法或具体方法开启事务,并指定相关事务属性。
原文:https://www.cnblogs.com/mini-Cat/p/13357762.html