SpringBoot教程(二十五) | SpringBoot集成AOP实现事务管理

转载:springboot项目事务配置 @Transactional注解及AOP实现全局事务管理

一、事务实现的前提

  1. 如果要使用@Transactional注解,推荐配置在方法上,粒度细
  2. 实际项目中还是推荐全局事务管理的,就怕有同事不写注解
  3. 使用全局事务的时候,方法命名一定要在上述规范中,切勿出现奇葩命名

二、事务失效的原因

  1. @Transactional注解默认只适用于public方法。
  2. 异常被捕获且未重新抛出,就是异常需要抛出,让程序知道报错了,事务才能进行被处理
  3. 不能在一个方法内部调用被@Transactional注解的方法(被@Transactional注解的方法需要是你的业务逻辑中最顶层的入口点。)

三、事务实现的方式

  1. @Transactional注解实现
  2. 全局事务管理器

1.@Transactional注解实现

配置在类上:

@Service("menuService")
@Transactional(rollbackFor = Exception.class)
public class MenuServiceImpl implements MenuService {

    @Resource
    private MenuMapper menuMapper;
    
 
   ......
}

配置在方法上:(推荐)

public class MenuServiceImpl implements MenuService {

    @Resource
    private MenuMapper menuMapper;

    @Override
    public List<MenuDto> getMenuInfo() {
        return menuMapper.getMenuInfo("1");
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public int insertMenuInfo(List<MenuDto> menuDtoList) {
        int insertMenuNum = menuMapper.insertMenu(menuDtoList);
        /*int a = 10/0;*/
        return insertMenuNum;
    }
}

那么有同学就要问了,如果你时配置在类跟方法上面呢,那肯定是方法上面的覆盖类上的,推荐方法上的原因是因为粒度更细。

参数解释:

(1)rollbackFor属性:是用于指定哪些异常会导致事务回滚。
在默认情况下,只有未检查的异常(RuntimeException及其子类)和错误(Error及其子类)会导致事务回滚。
所以一般来说我们会改成 rollbackFor = Exception.class

(2)propagation属性:用于定义事务的传播行为。
在默认情况下 propagation 为 Propagation.REQUIRED。
所以一般来说,使用默认的即可,我们是不需要去设置的。

2.全局事务管理器(强烈推荐)

参数注意

RuleBasedTransactionAttribute 的 setTimeout 不能乱设置,这个是指事务允许运行的最长时间(以秒为单位)。需要根据你实际业务接口处理时间为基准的。默认-1,永不超时。

package com.yang.demo.aop;

import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.*;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * 全局事务管理器
 *
 * @author yanglei
 * @date 2020/8/3
 */
@Aspect
@Configuration
public class TransactionalAopConfig {

    /**
     * 配置方法过期时间,默认-1,永不超时
     */
    private final static int METHOD_TIME_OUT = 120;

    /**
     * 配置切入点表达式
     */
    private static final String POINTCUT_EXPRESSION = "execution(* com.yang.demo.service..*.*(..))";

    /**
     * 事务管理器
     */
    @Resource
    private PlatformTransactionManager transactionManager;


    @Bean
    public TransactionInterceptor txAdvice() {
        /*事务管理规则,声明具备事务管理的方法名**/
        NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
        /*只读事务,不做更新操作*/
        RuleBasedTransactionAttribute readOnly = new RuleBasedTransactionAttribute();
        readOnly.setReadOnly(true);
        readOnly.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
        /*当前存在事务就使用当前事务,当前不存在事务就创建一个新的事务*/
        RuleBasedTransactionAttribute required = new RuleBasedTransactionAttribute();
        /*抛出异常后执行切点回滚,这边你可以更换异常的类型*/
        required.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
        /*PROPAGATION_REQUIRED:事务隔离性为1,若当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值*/
        required.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        /*设置事务失效时间,如果超过120秒,则回滚事务*/
        //required.setTimeout(METHOD_TIME_OUT);
        Map<String, TransactionAttribute> attributesMap = new HashMap<>(30);
        //设置增删改上传等使用事务
        attributesMap.put("save*", required);
        attributesMap.put("remove*", required);
        attributesMap.put("update*", required);
        attributesMap.put("batch*", required);
        attributesMap.put("clear*", required);
        attributesMap.put("add*", required);
        attributesMap.put("append*", required);
        attributesMap.put("modify*", required);
        attributesMap.put("edit*", required);
        attributesMap.put("insert*", required);
        attributesMap.put("delete*", required);
        attributesMap.put("do*", required);
        attributesMap.put("create*", required);
        attributesMap.put("import*", required);
        //查询开启只读
        attributesMap.put("select*", readOnly);
        attributesMap.put("get*", readOnly);
        attributesMap.put("valid*", readOnly);
        attributesMap.put("list*", readOnly);
        attributesMap.put("count*", readOnly);
        attributesMap.put("find*", readOnly);
        attributesMap.put("load*", readOnly);
        attributesMap.put("search*", readOnly);
        source.setNameMap(attributesMap);
        return new TransactionInterceptor(transactionManager, source);
    }

    /**
     * 设置切面=切点pointcut+通知TxAdvice
     */
    @Bean
    public Advisor txAdviceAdvisor() {
        /* 声明切点的面:切面就是通知和切入点的结合。通知和切入点共同定义了关于切面的全部内容——它的功能、在何时和何地完成其功能*/
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        /*声明和设置需要拦截的方法,用切点语言描写*/
        pointcut.setExpression(POINTCUT_EXPRESSION);
        /*设置切面=切点pointcut+通知TxAdvice*/
        return new DefaultPointcutAdvisor(pointcut, txAdvice());
    }

}


这边呢,根据自己的需求更改attributesMap的内容等

结论:我喜欢全局事务管理,嘿嘿

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值