正确实现了参数日志、异常日志、成功失败打点(含耗时统计)等功能。
下面我们创建一个Controller来测试一下是否可以自动切入Controller:
运行程序打开浏览器访问: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事务控制切面优先级低: @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。