Custom transaction annotation based on springboot

Custom transaction annotation based on springboot

1. Turn on annotation support (springboot supports annotations by default)
2. Custom annotation interface
3. Write transaction class
4. Write aspect class

2. Custom annotation interface

import java.lang.annotation.*;


/**
 * 注解类
 */
@Target(ElementType.METHOD)             //定义注解用在方法上
@Retention(RetentionPolicy.RUNTIME)     //运行时注解
@Documented
public @interface CustomTransaction {
    
    
    String value() default "";
}

3. Write transaction class

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;

@Component
@Scope(value = "prototype")
public class TransactionUtils {
    
    


    @Autowired
    private DataSourceTransactionManager dataSourceTransactionManager;

    /**
     *初始化创建TransactionStatus对象
     * @return
     */
    public TransactionStatus init(){
    
    
        System.out.println("创建事务了...");
        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());
        return transactionStatus;
    }

    /**
     * 提交事务
     * @param transactionStatus
     */
    public void commit(TransactionStatus transactionStatus){
    
    
        System.out.println("提交事务...");
        dataSourceTransactionManager.commit(transactionStatus);
    }


    public void rollback(TransactionStatus transactionStatus){
    
    
        System.out.println("事务回滚了....");
        dataSourceTransactionManager.rollback(transactionStatus);
    }
}

4. Writing aspects

import io.tianma.common.annotation.CustomTransaction;
import io.tianma.common.utils.TransactionUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;

import java.lang.reflect.Method;

@Aspect
@Component
public class CustomTransactionAspect {
    
    

    @Autowired
    TransactionUtils transactionUtils;

    /**
     * 选择切面的注解CustomTransaction
     */
    @Pointcut("@annotation(io.tianma.common.annotation.CustomTransaction)")
    public void transactionPointCut() {
    
    

    }

    /**
     * 方法增强@Arounbd
     * @param point
     */
    @Around("transactionPointCut()")
    public void around(ProceedingJoinPoint point){
    
    
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();//获取到方法对象

        //获取到注解类
        CustomTransaction annotation = method.getAnnotation(CustomTransaction.class);
        if(annotation != null){
    
    
            System.out.println(annotation.value());//打印注解上value的内容
        }

        //请求的类名以及方法名
        String className = point.getTarget().getClass().getName();
        String methodName = signature.getName();
        System.out.println("执行的方法为:" + className + "." + methodName + "()");

        //开启事务
        TransactionStatus transactionStatus = transactionUtils.init();

        try {
    
    
            //执行方法
            point.proceed();

            //执行成功提交事务
            transactionUtils.commit(transactionStatus);
        } catch (Throwable throwable) {
    
    
            //执行方法出错则回滚事务
            transactionUtils.rollback(transactionStatus);
        }
    }
}

5. Project service

    @Override
   @CustomTransaction("新增用户开启事务")
   public void saveUser() {
    
    
      SysUserEntity user = new SysUserEntity();
      user.setUserId("D123456");
      user.setName("张三");
      user.setCreateUserId("D123456");
      user.setCreateTime(new Date());
      this.save(user);

//    System.out.println(1/0);

      SysUserRoleEntity sysUserRoleEntity = new SysUserRoleEntity();
      sysUserRoleEntity.setRoleId(123456L);
      sysUserRoleEntity.setUserId("123456");

      sysUserRoleService.save(sysUserRoleEntity);
   }

6. Query the database first

Insert picture description here
Insert picture description here
No data in the query database

7. Call API

Insert picture description here

It can be seen that the console has been executed successfully
and query the database again.
Insert picture description here
Insert picture description here
You can see that a record has been generated and the aspect has been executed.

8. Open the comment (System.out.println(1/0)), and change user_id to D1234567

SysUserEntity user = new SysUserEntity();
user.setUserId("D1234567");
user.setName("张三");
user.setCreateUserId("D1234567");
user.setCreateTime(new Date());
this.save(user);

System.out.println(1/0);

SysUserRoleEntity sysUserRoleEntity = new SysUserRoleEntity();
sysUserRoleEntity.setRoleId(1234567L);
sysUserRoleEntity.setUserId("1234567");

sysUserRoleService.save(sysUserRoleEntity);

Insert picture description here
It can be seen that the transaction is rolled back, query the database again
Insert picture description here
Insert picture description here

You can see that the transaction was not committed after the error was reported, but rolled back

end

Since then, the custom transaction annotation based on springboot has been completed

Guess you like

Origin blog.csdn.net/weixin_44333767/article/details/109326132