手写spring编程事务
微信公众号:用心程序员
编程事务和声明事务的区别
编程式事务:编码方式实现事务管理。需要你在代码中直接加入处理事务的逻辑,可能需要在代码中显式调用beginTransaction()、commit()、rollback()等事务管理相关的方法,如在执行a方法时候需要事务处理,你需要在a方法开始时候开启事务,处理完后。在方法结束时候,关闭事务。
声明式事务:声明式的事务的做法是在a方法外围添加注解或者直接在配置文件中定义,a方法需要事务处理,在spring中会通过配置文件在a方法前后拦截,并添加事务。声明式事务属于无侵入式,不会影响业务逻辑的实现。
实现过程
建立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>5.1.37</version>
</dependency>
</dependencies>
####第二步 编写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"
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">
<context:component-scan base-package="ljx"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy> <!-- 开启事物注解 -->
<!-- 1. 数据源对象: C3P0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
<property name="user" value="root"></property>
<property name="password" value=""></property>
</bean>
<!-- 2. JdbcTemplate工具类实例 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 3.配置事务 -->
<bean id="dataSourceTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
####第三步 编写dao层
@Repository
public class UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public void add(String name, int age){
String sql = "insert into tb_user(name, age) values (?,?)";
int udateResult = jdbcTemplate.update(sql,name,age);
System.out.println("updateResult:" + udateResult);
}
}
####第四步 编写事务工具类TransactionUtils
//编程事务(需要手动begin 手动回滚 手都提交)
@Component
public class TransactionUtils {
// 获取事务源
@Autowired
private DataSourceTransactionManager dataSourceTransactionManager;
// 开启事务
public TransactionStatus begin() {
TransactionStatus transaction = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());
return transaction;
}
// 提交事务
public void commit(TransactionStatus transaction) {
dataSourceTransactionManager.commit(transaction);
}
// 回滚事务
public void rollback(TransactionStatus transaction) {
dataSourceTransactionManager.rollback(transaction);
}
}
####第五步 编写service层
@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();
userDao.add("张三",13);
int i = 1/0;
System.out.println("############################");
userDao.add("李四", 14);
//提交事务
if (transactionStatus != null){
transactionUtils.commit(transactionStatus);
}
}catch (Exception e){
e.getMessage();
//回滚事务
if (transactionStatus != null)
transactionUtils.rollback(transactionStatus);
}
}
}
####第六步 测试
public class test01 {
public static void main(String[] args){
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = (UserService) classPathXmlApplicationContext.getBean("userServiceImpl");
userService.add();
}
}
使用Aop整合编程事务
####第一步 编写切面类AopTransaction
@Component
@Aspect
public class AopTransaction {
@Autowired
private TransactionUtils transactionUtils;
// TransactionUtils 不要实现为单例子: 如果为单例子的话可能会发生线程安全问题
// // 异常通知
@AfterThrowing("execution(* ljx.service.UserService.add(..))")
public void afterThrowing() {
System.out.println("回滚事务");
// 获取当前事务 直接回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
// 环绕通知 在方法之前和之后处理事情
@Around("execution(* ljx.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);
}
}
####第二步 重构service层
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Autowired
private TransactionUtils transactionUtils;
@Override
public void add(){
userDao.add("张三",13);
int i = 1/0;
System.out.println("############################");
userDao.add("李四", 14);
}
}
####第三步 测试
public class test01 {
public static void main(String[] args){
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = (UserService) classPathXmlApplicationContext.getBean("userServiceImpl");
userService.add();
}
}
项目源码:https://github.com/ljx95/springDemo01