如何在Spring的@Transaction层面上对异常进行日志记录?

在没使用@Transaction之前,我的业务代码模型大概就是下面这样:

        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(def);

        try {
            studentMapper.insertOnestdent(student);
            logger.info("Insert one record successfully: " + student.toString());
        } catch (Exception ex) {
            dataSourceTransactionManager.rollback(transactionStatus);
            // ex.printStackTrace();
            logger.error("Insert one record unsuccessfully: " + student.toString());
            return false;
        }
        dataSourceTransactionManager.commit(transactionStatus);
        return true;

类似上面这样的话不管我上面的数据库操作执行成功还是执行失败,我在日志中都可以得到反馈。

但是上面这样的做法,会造成大量的代码的重复,利用spring提供的aop可以实现这样的日志功能,但是后来看文档发现有一个@Transaction注解,使用这个注解,代码可以简化成下面这个样子:

    @Transactional(rollbackFor = Exception.class)
    public boolean insertOneStudent(Student student) {
        studentMapper.insertOneStudent(student);
        logger.info("Insert one student successfully" + student.toString());
        return true;
    }

这样当数据库操作执行成功的时候我可以日志中成功的进行记录,但是这样的话当插入操作执行失败的时候我应该如何在日志中进行记录。

我现在的初步想法是自己手动实现一个类似@Transaction的动态反射的功能,这样每个要影响数据库中的数据修改的方法执行的时候我都在动态反射的invoke()方法中进行异常的try catch的处理。但是不知道spring是否内置这样的功能?

p.s: 我尽量想将数据库的操作与处理全部放在service层面来处理,不想将日志记录的往上面抛。

insertOneStudent方法整个try catch

try {
...
} catch (Exception e) {
    logger.error(e.getMessage(), e);
    throw e;
}

或者实现@RestControllerAdvice,在里面统一打印异常日志
像这样:

@RestControllerAdvice
public class MyExceptionHandler {

    @ExceptionHandler(value = Exception.class)
    public Object exceptionHandler(HttpServletRequest request,
                                         Exception exception) {
        logger.warn("异常:", exception);
        ...
    }
}

spring也有提供切面的异常处理

<!--aop配置 -->
    <aop:config>
        <!-- 业务类切面 -->
        <aop:pointcut id="【切面ID】"
            expression="【这里填写切面的匹配规则】" />
        <!-- 异常处理 -->
        <aop:aspect ref="【处理异常的类ID】">
            <aop:after-throwing method="【处理异常的方法名称】" pointcut-ref="【切面ID】" throwing="e" />
        </aop:aspect>
    </aop:config>

当然,有xml配置就会有注解配置。主要有下面几个注解

  • @Aspect 声明切面配置

  • @Pointcut 声明切面

  • @AfterThrowing 声明处理方法

注意事项:

  1. 处理异常的类是不需要实现任何接口和继承任何类的。

  2. 处理异常的方法要声明两个参数(不声明也可以,获取不了异常信息而已),举个例子

    public void test(JoinPoint joinPoint, Exception e)

    其中joinPoint参数可以获取抛出异常的方法参数信息,Exception对象就不用说了吧。

  3. 以上内容仅做参考,spring的版本不同也可能会导致上述说明和实际情况有差异,想获取标准的说明请参阅Spring的官方文档

  • 想在html里面加个判断,该怎么加?
  • springboot项目如何记住当前用户
  • idea 如何像eclipse 那样自动生成自定义的代码注释
  • Spring gradle 构建 eclipse,在spring目录下build.gradle怎么把国外源换成国内阿里源呢?
  • 这种编码是什么编码应该怎么解码?
  • sysbench cpu测试的结果看不懂,求解
  • java http 请求参数都需要URLEncoder.encode吗
  • php如何过滤unicode编码?
  • SQL中,使用Foreign Key存放与普通类型字段存放有什么区别?
  • 问下,控制台Network显示有数据,但是console里面却显示为空字符串,有遇到类似情况的嘛
  • 微博的浏览次数是怎么实现的?