你未必出类拔萃,但一定与众不同
手写简易Spring事务框架
前言
该篇需要一些框架基础
在spring中数据库事务时通过PlatformTransactionManager进行管理的,单凭他自身是无法支持事务的,而能够支持事务的是org.springframework.transaction.support.TransactionTemplate模板 他是Spring所提供的事务管理器的模板 以下是一段重要源码
public class TransactionTemplate extends DefaultTransactionDefinition implements TransactionOperations, InitializingBean {
protected final Log logger = LogFactory.getLog(this.getClass());
private PlatformTransactionManager transactionManager;
public TransactionTemplate() {
}
...................
public <T> T execute(TransactionCallback<T> action) throws TransactionException {
if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
return ((CallbackPreferringPlatformTransactionManager)this.transactionManager).execute(this, action);
} else {
TransactionStatus status = this.transactionManager.getTransaction(this);
Object result;
try {
result = action.doInTransaction(status);
} catch (RuntimeException var5) {
this.rollbackOnException(status, var5);
throw var5;
} catch (Error var6) {
this.rollbackOnException(status, var6);
throw var6;
} catch (Exception var7) {
this.rollbackOnException(status, var7);
throw new UndeclaredThrowableException(var7, "TransactionCallback threw undeclared checked exception");
}
this.transactionManager.commit(status);
return result;
}
}
PlatformTransactionManager
public interface PlatformTransactionManager {
TransactionStatus getTransaction(TransactionDefinition var1) throws TransactionException;
void commit(TransactionStatus var1) throws TransactionException;
void rollback(TransactionStatus var1) throws TransactionException;
}
接下来就进入正题手写Spring事务框架 这里使用编程式事务
(当前这个方式已经不是主流了,甚至几乎不被推荐,但是因为代码流程更为清晰,方便阅读)
内容
创建maven项目
导入依赖
<dependencies>
<!-- 引入Spring-AOP等相关Jar -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.5.3</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.1_2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
</dependencies>
UserDao
@Repository
public class UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public void add(String name, String password) {
String sql = "INSERT INTO user_list(user_name, user_password) VALUES(?,?);";
int updateResult = jdbcTemplate.update(sql, name, password);
System.out.println("updateResult:" + updateResult);
}
}
UserService
public interface UserService {
public void add();
}
UserServiceImpl
TransactionStatus表示一个事物的状态。接口提供了控制事务执行和查询事务状态的方法。比如当前调用栈中之前已经存在了一个事物,那么就是通过该接口来判断的,TransactionStatus接口可以让事务管理器控制事务的执行,比如检查事务是否为一个新事务,或者是否只读,TransactionStatus还可以初始化回滚操作。
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Autowired
private TransactionUtils transactionUtils;
@Override
public void add() {
TransactionStatus transactionStatus = null;
try {
transactionStatus = transactionUtils.begin();
System.out.println("-------");
userDao.add("java","123456");
System.out.println("-------");
transactionUtils.commit(transactionStatus);
}catch (Exception e){
e.printStackTrace();
if(transactionStatus == null){
transactionUtils.rollback(transactionStatus);
}
}
}
}
Spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.bluedot"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/bank?useSSL=false&serverTimezone=GMT"></property>
<property name="user" value="root"></property>
<property name="password" value="520560"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="dataSourceTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<tx:annotation-driven transaction-manager="dataSourceTransactionManager" />
</beans>
TransactionUtils
使用DataSourceTransactionManager去定义数据库事务管理器
并且开启这个事物 这样spring就知道将数据库事务委托给事务管理器信息管理
数据库的资源的产生和释放如果没有委托给数据库管理器,那么就由JdbcTemplate管理,而这时委托给了事务管理器,所以JdbcTemplate的数据库资源和事务交由事务管理器处理
@Component
public class TransactionUtils {
@Autowired
private DataSourceTransactionManager dataSourceTransactionManager;
public TransactionStatus begin(){
System.out.println("事务开始");
TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());
return transactionStatus;
}
public void commit(TransactionStatus transactionStatus){
System.out.println("开始提交事务");
dataSourceTransactionManager.commit(transactionStatus);
}
public void rollback(TransactionStatus transactionStatus){
System.out.println("事务回滚!!!");
dataSourceTransactionManager.rollback(transactionStatus);
}
}
测试类Test
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = (UserService) classPathXmlApplicationContext.getBean("userServiceImpl");
userService.add();
}
}
未出现异常时 成功提交
事务开始
-------
updateResult:1
-------
开始提交事务
整合aop实现Spring事务框架
AopTransaction
@Component
@Aspect
public class AopTransaction {
@Autowired
private TransactionUtils transactionUtils;
@AfterThrowing("execution(* com.bluedot.service.UserService.add(..))")
public void afterThrow(){
System.out.println("异常通知 回滚事务");
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
@Around("execution(* com.bluedot.service.UserService.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕通知 开启事务");
TransactionStatus transactionStatus = transactionUtils.begin();
proceedingJoinPoint.proceed();
System.out.println("环绕通知 提交事务");
transactionUtils.commit(transactionStatus);
}
}
修改UserServiceImpl
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Autowired
private TransactionUtils transactionUtils;
@Override
public void add() {
System.out.println("-------");
userDao.add("Spring","123456");
int i = 1/0;
System.out.println("-------");
}
}
出现异常时 事务成功回滚
环绕通知 开启事务
事务开始
-------
updateResult:1
异常通知 回滚事务
Exception in thread "main" org.springframework.transaction.NoTransactionException: No transaction aspect-managed TransactionStatus in scope
|