手写spring事务

1. 背景:
在spingboot框架搭建的项目中,利用了反射机制调用了service中的方法,导致spring注入的对象全部为null值不可使用,同时spring框架提供的@Transactional注解也失效。为了解决事务回滚失效的问题 ,利用放射类动态代理 以及手写事务的方式来解决反射引起的以上问题。

2.transactionalUtils.java类的编写

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;

@Component
public class TransactionUtils {
	
	@Autowired
	private DataSourceTransactionManager dataSourceTransactionManager;
	
	// 开启事务
	public TransactionStatus begin() {
		TransactionStatus transaction = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());
		return transaction;
	}
	 
	// 提交事务
	public void commit(TransactionStatus transactionStatus) {
		dataSourceTransactionManager.commit(transactionStatus);
	}
	 
	// 回滚事务
	public void rollback(TransactionStatus transactionStatus) {
		dataSourceTransactionManager.rollback(transactionStatus);
	}

}

3.被反射的service类的Java反射动态代理

 //反射类调用 动态代理 开始
    public static ServiceImpl dynamicProxy;  //ServiceImpl 为当前类

    @PostConstruct
    public void init() {
        System.out.println("dynamicProxy init");
        dynamicProxy = this;
    }

从Java EE 5规范开始,Servlet中增加了两个影响Servlet生命周期的注解(Annotion);@PostConstruct和@PreDestroy。这两个注解被用来修饰一个非静态的void()方法 。
被@PostConstruct修饰的方法会在服务器加载Servle的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行。PreDestroy()方法在destroy()方法执行执行之后执行。
在当前的ServiceImpl .java中通过@Autowired注入的所有java类,在调用时都通过动态代理对象dynamicProxy来获得,例如:

//通过orderId 查询出所有的资源id的信息
        Set<Long> resIdSet = dynamicProxy.itrmOrderResMapper.getResIdSetByOrderId(order.getOrderBase().getId());

4.手写事务的添加
在ServiceImpl中注入第一步写好的transactionUtils的工具类

@Autowired
	private TransactionUtils transactionUtils;

在需要添加事务的方法中开启事务。

TransactionStatus transactionStatus = null;

//手动开启事物
transactionStatus = dynamicProxy.transactionUtils.begin();
//手动回滚事务
dynamicProxy.transactionUtils.rollback(transactionStatus);
//手动结束事务,提交事务
dynamicProxy.transactionUtils.commit(transactionStatus);

//可以设置断点 断点名称为:firatSavepoint 
Object firatSavepoint = transactionStatus.createSavepoint();
//手动混滚事务致断点 firatSavepoint 的设定处
transactionStatus.rollbackToSavepoint(firatSavepoint);

TransactionStatus接口可以让事务管理器控制事务的执行,可以检查事务是不是一个新事务,或者是否只读。TransactionStatus还可以初始化回滚操作。

5.原理概述
Spring框架支持事务管理的核心是事务管理器抽象,对于不同的数据访问框架(如Hibernate)通过实现策略接口PlatformTransactionManager,从而能支持各种数据访问框架的事务管理

getTransaction():返回一个已经激活的事务或创建一个新的事务(根据给定的TransactionDefinition类型参数定义的事务属性),返回的是TransactionStatus对象代表了当前事务的状态,其中该方法抛出TransactionException(未检查异常)表示事务由于某种原因失败。
commit():用于提交TransactionStatus参数代表的事务,具体语义请参考Spring Javadoc;
rollback():用于回滚TransactionStatus参数代表的事务,具体语义请参考Spring Javadoc。

猜你喜欢

转载自blog.csdn.net/zhangsuhua0702/article/details/82386400
今日推荐