朱晔和你聊Spring系列S1E6:容易犯错的Spring AOP (7)

正确实现了参数日志、异常日志、成功失败打点(含耗时统计)等功能。
下面我们创建一个Controller来测试一下是否可以自动切入Controller:

package me.josephzhu.spring101aop; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ResponseBody; import java.util.List; @Controller public class MyController { @Autowired private DbMapper dbMapper; @ResponseBody @GetMapping("/data") public List<MyBean> getPersonList(){ return dbMapper.getPersonList(); } }

运行程序打开浏览器访问:8080/data后能看到如下输出:

2018-10-07 10:49:53.811 INFO 19737 --- [nio-8080-exec-1] me.josephzhu.spring101aop.MetricsAspect : 【入参日志】调用 【class me.josephzhu.spring101aop.MyController】【public java.util.List me.josephzhu.spring101aop.MyController.getPersonList()】【:8080/data】 的参数是:【[]】 2018-10-07 10:49:53.819 INFO 19737 --- [nio-8080-exec-1] me.josephzhu.spring101aop.MetricsAspect : 【成功打点】调用 【class me.josephzhu.spring101aop.MyController】【public java.util.List me.josephzhu.spring101aop.MyController.getPersonList()】【:8080/data】 成功,耗时:PT-0.008S 2018-10-07 10:49:53.819 INFO 19737 --- [nio-8080-exec-1] me.josephzhu.spring101aop.MetricsAspect : 【出参日志】调用 【class me.josephzhu.spring101aop.MyController】【public java.util.List me.josephzhu.spring101aop.MyController.getPersonList()】【:8080/data】 的返回是:【[MyBean(id=1, name=zhuye, age=35, balance=1000), MyBean(id=2, name=zhuye, age=35, balance=1000)]】

最后,我们再来踩一个坑。我们来测一下ignoreException吞掉异常的功能(默认为false):

@Transactional(rollbackFor = Exception.class) @Override @Metrics(ignoreException = true) public void insertData(boolean success){ dbMapper.personInsertWithoutId(); if(!success) dbMapper.personInsertWithId(); }

这个功能会吞掉异常,在和Transactional事务管理结合时候会不会出问题呢?
开启这个配置后刷新页面可以看到数据库内有三条记录了,说明第二次的insertData方法执行没有成功回滚事务。这也是合情合理的,毕竟我们的MetricsAspect吃掉了异常。

朱晔和你聊Spring系列S1E6:容易犯错的Spring AOP


怎么绕开这个问题呢?答案是我们需要手动控制一下我们的切面的执行优先级,我们希望这个切面优先级比Spring事务控制切面优先级低:

@Aspect @Component @Slf4j @Order(1) public class MetricsAspect {

再次运行程序可以看到事务正确回滚。

总结

本文我们通过一些例子覆盖了如下内容:

Spring AOP的一些基本知识点。

Mybatis和H2的简单配置使用。

如何实现Spring事务管理。

如何切换为AspjectJ进行AOP。

观察JDK代理和CGLIB代理。

如何定义切面实现事务后处理和日志异常打点这种横切关注点。

在整个过程中,也踩了下面的坑,印证的本文的标题:

Spring AOP代理不能作用于代理类内部this方法调用的坑。

Spring AOP实例化切面默认单例的坑。

AJC编译器无法支持lambok的坑。

切面优先级顺序的坑。

切面内部获取注解方式的坑。

老样子,本系列文章代码见我的github:https://github.com/JosephZhu1983/Spring101。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzfgzw.html