博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
手写 | spring事务
阅读量:3889 次
发布时间:2019-05-23

本文共 10482 字,大约阅读时间需要 34 分钟。

编程事务实现:

/>
@Componentpublic 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); }}
public class UserDao {
@Autowired private JdbcTemplate jdbcTemplate; public void add(String name, Integer age) {
String sql = "INSERT INTO users(NAME, age) VALUES(?,?);"; int update = jdbcTemplate.update(sql, name, age); System.out.println("insertResult:" + update); }}
@Servicepublic class UserService {
@Autowired private UserDao userDao; @Autowired private TransactionUtils transactionUtils; public void add() {
TransactionStatus transactionStatus = null; try {
transactionStatus = transactionUtils.begin(); userDao.add("wangmazi", 27); int i = 1 / 0; System.out.println("我是add方法"); userDao.add("zhangsan", 16); transactionUtils.commit(transactionStatus); } catch (Exception e) {
e.printStackTrace(); } finally {
if (transactionStatus != null) {
transactionStatus.rollbackToSavepoint(transactionStatus); } } }}

AOP技术封装手动事务:

@Component@Aspectpublic class AopTransaction {
@Autowired private TransactionUtils transactionUtils; // // 异常通知 @AfterThrowing("execution(* com.itmayiedu.service.UserService.add(..))") public void afterThrowing() {
System.out.println("程序已经回滚"); // 获取程序当前事务 进行回滚 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } // 环绕通知 @Around("execution(* com.itmayiedu.service.UserService.add(..))") public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("开启事务"); TransactionStatus begin = transactionUtils.begin(); proceedingJoinPoint.proceed(); transactionUtils.commit(begin); System.out.println("提交事务"); }}

如果使用了try捕获异常时.一定要在catch里面手动回滚。

事务手动回滚代码
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

声明事务实现:

管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。

显然声明式事务管理要优于编程式事务管理,这正是spring倡导的非侵入式的开发方式。

声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就可以获得完全的事务支持。和编程式事务相比,声明式事务唯一不足地方是,后者的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。但是即便有这样的需求,也存在很多变通的方法,比如,可以将需要进行事务管理的代码块独立为方法等等。

配置:

用法:@Transactional

手写Spring注解版本事务:

实现自定义注解

元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解:

@Target

@Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。

在这里插入图片描述

1.CONSTRUCTOR:用于描述构造器
2.FIELD:用于描述域
3.LOCAL_VARIABLE:用于描述局部变量
4.METHOD:用于描述方法
5.PACKAGE:用于描述包
6.PARAMETER:用于描述参数
7.TYPE:用于描述类、接口(包括注解类型) 或enum声明

2.@Retention

表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
3.@Documented
4.@Inherited
使用@interface 定义注解。

自定义注解案例:

/** * 自定义注解 * * @author 孙一鸣 on 2020/2/27 * @interface 定义注解 */@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface MyAnnotation {
int userId() default 0; String userName() default "默认名称"; String[] arrs();}

如何通过反射获取注解信息:

/** * @author 孙一鸣 on 2020/2/27 * 测试注解 */public class User {
@MyAnnotation(userId = 1, userName = "孙一", arrs = {
"1"}) public void add() {
} public void del() {
} public static void main(String[] args) throws ClassNotFoundException {
//如何获取注解信息? --- 反射 Class
UserClass = Class.forName("Annotation.User"); //获取当前类 不包括父类的所有方法 Method[] methods = UserClass.getDeclaredMethods(); for (Method method : methods) {
//获取该方法是否有注解 MyAnnotation myAnnotation = method.getDeclaredAnnotation(MyAnnotation.class); if (myAnnotation == null) {
System.out.println(method.getName() + "该方法上没有注解..."); continue; } System.out.println("userID " + myAnnotation.userId()); System.out.println("userName " + myAnnotation.userName()); System.out.println("arrs " + myAnnotation.arrs().toString()); } }}

手写Spring事务注解思路:

在这里插入图片描述

代码实现:

在这里插入图片描述

4.0.0
newSpring
Annotation
1.0-SNAPSHOT
org.springframework
spring-core
4.3.7.RELEASE
org.springframework
spring-beans
4.3.7.RELEASE
org.springframework
spring-context
4.3.7.RELEASE
org.springframework
spring-aspects
4.3.7.RELEASE
org.springframework
spring-jdbc
4.3.7.RELEASE
mysql
mysql-connector-java
5.1.41
com.mchange
c3p0
0.9.5.1
package com.sym.aop;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;//自定义事务注解@Target(value = {
ElementType.METHOD })@Retention(RetentionPolicy.RUNTIME)public @interface ExtTransaction {
}
package com.sym.aop;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Scope;import org.springframework.jdbc.datasource.DataSourceTransactionManager;import org.springframework.stereotype.Component;import org.springframework.transaction.TransactionStatus;import org.springframework.transaction.interceptor.DefaultTransactionAttribute;//编程事务(需要手动begin 手动回滚  手都提交)@Component()@Scope("prototype") // 设置成原型解决线程安全public class TransactionUtils {
private TransactionStatus transactionStatus; // 获取事务源 @Autowired private DataSourceTransactionManager dataSourceTransactionManager; // 开启事务 public TransactionStatus begin() {
transactionStatus = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute()); return transactionStatus; } // 提交事务 public void commit(TransactionStatus transaction) {
dataSourceTransactionManager.commit(transaction); } // 回滚事务 public void rollback() {
System.out.println("rollback"); dataSourceTransactionManager.rollback(transactionStatus); }}
package com.sym.aop;import java.lang.reflect.Method;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import org.springframework.transaction.TransactionStatus;import org.springframework.transaction.interceptor.TransactionAspectSupport;@Component@Aspectpublic class AopExtTransaction {
@Autowired private TransactionUtils transactionUtils; @AfterThrowing("execution(public void com.sym.dao.UserDao.*(..))") public void afterThrowing() throws NoSuchMethodException, SecurityException {
// isRollback(proceedingJoinPoint); System.out.println("程序发生异常"); // TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); // TransactionStatus currentTransactionStatus = // TransactionAspectSupport.currentTransactionStatus(); // System.out.println("currentTransactionStatus:" + // currentTransactionStatus); transactionUtils.rollback(); } // // 环绕通知 在方法之前和之后处理事情 @Around("execution(public void com.sym.dao.UserDao.*(..))") public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
// 调用方法之前执行 TransactionStatus transactionStatus = begin(proceedingJoinPoint); proceedingJoinPoint.proceed();// 代理调用方法 注意点: 如果调用方法抛出异常不会执行后面代码 // 调用方法之后执行 commit(transactionStatus); } public TransactionStatus begin(ProceedingJoinPoint pjp) throws NoSuchMethodException, SecurityException {
// // 判断是否有自定义事务注解 ExtTransaction declaredAnnotation = getExtTransaction(pjp); if (declaredAnnotation == null) {
return null; } // 如果有自定义事务注解,开启事务 System.out.println("开启事务"); TransactionStatus transactionStatu = transactionUtils.begin(); return transactionStatu; } public void commit(TransactionStatus transactionStatu) {
if (transactionStatu != null) {
// 提交事务 System.out.println("提交事务"); transactionUtils.commit(transactionStatu); } } public ExtTransaction getExtTransaction(ProceedingJoinPoint pjp) throws NoSuchMethodException, SecurityException {
// 获取方法名称 String methodName = pjp.getSignature().getName(); // 获取目标对象 Class
classTarget = pjp.getTarget().getClass(); // 获取目标对象类型 Class
[] par = ((MethodSignature) pjp.getSignature()).getParameterTypes(); // 获取目标对象方法 Method objMethod = classTarget.getMethod(methodName, par); // // 判断是否有自定义事务注解 ExtTransaction declaredAnnotation = objMethod.getDeclaredAnnotation(ExtTransaction.class); if (declaredAnnotation == null) {
System.out.println("您的方法上,没有加入注解!"); return null; } return declaredAnnotation; } // 回滚事务 public void isRollback(ProceedingJoinPoint pjp) throws NoSuchMethodException, SecurityException {
// // 判断是否有自定义事务注解 ExtTransaction declaredAnnotation = getExtTransaction(pjp); if (declaredAnnotation != null) {
System.out.println("已经开始回滚事务"); // 获取当前事务 直接回滚 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); return; } }}

转载地址:http://zmthn.baihongyu.com/

你可能感兴趣的文章
PHP获取客户端的IP
查看>>
从头开始学习yii2---1.搭建yii2开发环境
查看>>
从头开始学习yii2---3.语言包的配置
查看>>
yii2-表单验证的一些规则
查看>>
索引相关问题
查看>>
php面试可能会被问道的技术题汇总
查看>>
php面试题1-线程和进程的区别(顺带提下协程)
查看>>
php面试题2-用到过的传输协议
查看>>
php面试题3-yii2和yii的不一样的地方
查看>>
IOS 一些好的框架和 技术大牛的博客
查看>>
Java 和 Object-c的区别
查看>>
Windows环境下Android NDK环境搭建
查看>>
NDK Build 用法(NDK Build)
查看>>
Android NDK开发起步Hello Jni
查看>>
[已解决]AutoCompleteTextView 不显示匹配的内容,因为将空的内容添加进去了
查看>>
object c 归档和解档,其实就是java中的序列化和反序列化
查看>>
object c的浅拷贝(地址拷贝)和深拷贝(对象拷贝)
查看>>
object c son字符串的解析
查看>>
object c 非常强大的类的属性复制kcv键值码赋值
查看>>
Java中普通代码块,构造代码块,静态代码块区别及代码示例
查看>>