Spring-mvc、Spring-boot中如何在调用同类方法时触发AOP

1. 问题描述

Spring-mvc和Spring-boot中aop可以实现代理的功能,我们可以借此实现事务和日志记录或者限流等多种操作。但是,如果你在一个方法中调用其同类下的其他方法的时候不会触发AOP。本文主要说明其原因及解决办法和实现原理。

2. 原因

AIOP的本质是,我们获取代理对象,该对象执行方法的时候,我们对其进行增强操作。例如:下图示例1中bicycle对象执行drive方法的时候,我们对其执行了增强。但是,如果我们在示例2中调用同类的其他方法的时候,本质使用this.drive(),此处的this是真实对象bicycle,而不是代理对象cglibProxy,因而不会进行增强。

3. 解决办法

3.1 直接从spring容器中获取

参考下图中方法all1,SpringUtils实现代码参考 SpringUtils

3.2 借助Aspectj获取代理对象

参考下图中方法all2

4. 解析

SpringUtils直接是创建对象后,在spring容器中管理,便于理解。此处主要解析3.2。在启动类添加@EnableAspectJAutoProxy(exposeProxy = true, proxyTargetClass = true)后,可以发现在调用spring对象方法之前,会先进入CglibAopProxy中,并将当前spring对象放到ThreadLocal中 ,使用的时候直接从threadLocal中取即可。相关源码贴图如下。

4.1 org.springframework.aop.framework.CglibAopProxy

4.2 org.springframework.aop.framework.AopContext

5. 总结

两种方法都是直接获取代理对象,调用目的方法达到方法增强的目的,并且都是相对成熟的实现方案。但是个人更喜欢前者(springUtils获取),原因在于无侵入,且大部分项目都会自定义该工具。后者相对于前者,或多或少存在一点开销。

相关推荐
在努力的前端小白3 小时前
Spring Boot 敏感词过滤组件实现:基于DFA算法的高效敏感词检测与替换
java·数据库·spring boot·文本处理·敏感词过滤·dfa算法·组件开发
一叶飘零_sweeeet6 小时前
从繁琐到优雅:Java Lambda 表达式全解析与实战指南
java·lambda·java8
艾伦~耶格尔6 小时前
【集合框架LinkedList底层添加元素机制】
java·开发语言·学习·面试
一只叫煤球的猫7 小时前
🕰 一个案例带你彻底搞懂延迟双删
java·后端·面试
最初的↘那颗心7 小时前
Flink Stream API 源码走读 - print()
java·大数据·hadoop·flink·实时计算
JH30737 小时前
Maven的三种项目打包方式——pom,jar,war的区别
java·maven·jar
带刺的坐椅8 小时前
轻量级流程编排框架,Solon Flow v3.5.0 发布
java·solon·workflow·flow·solon-flow
David爱编程9 小时前
线程调度策略详解:时间片轮转 vs 优先级机制,面试常考!
java·后端
阿冲Runner9 小时前
创建一个生产可用的线程池
java·后端
写bug写bug10 小时前
你真的会用枚举吗
java·后端·设计模式