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获取),原因在于无侵入,且大部分项目都会自定义该工具。后者相对于前者,或多或少存在一点开销。

相关推荐
爱的叹息1 小时前
spring mvc 中 RestTemplate 全面详解及示例
java·spring·mvc
.生产的驴5 小时前
SpringBoot 接口限流Lua脚本接合Redis 服务熔断 自定义注解 接口保护
java·大数据·数据库·spring boot·redis·后端·lua
洛可可白6 小时前
Spring Boot中自定义注解的创建与使用
java·spring boot·后端
Alkaid:7 小时前
解决Long类型前端精度丢失和正常传回后端问题
java·前端·javascript·vue.js
唐人街都是苦瓜脸7 小时前
Java RPC 框架是什么
java·开发语言·rpc
魔道不误砍柴功7 小时前
Java性能调优2025:从JVM到Kubernetes的全链路优化策略
java·jvm·kubernetes
爱吃鱼饼的猫8 小时前
【SpringBoot篇】如何使用CommandLineRunner实现缓存预热
spring boot·spring·缓存
多云的夏天8 小时前
C++-FFmpeg-(5)-1-ffmpeg原理-ffmpeg编码接口-AVFrame-AVPacket-最简单demo
java·开发语言
无名之逆8 小时前
[特殊字符] Hyperlane:Rust 高性能 HTTP 服务器库,开启 Web 服务新纪元!
java·服务器·开发语言·前端·网络·http·rust
别来无恙2028 小时前
JAVA类和对象
java·开发语言