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

相关推荐
sheji34166 分钟前
【开题答辩全过程】以 基于springboot的扶贫系统为例,包含答辩的问题和答案
java·spring boot·后端
m0_726965981 小时前
面面面,面面(1)
java·开发语言
代码栈上的思考1 小时前
消息队列:内存与磁盘数据中心设计与实现
后端·spring
xuhaoyu_cpp_java1 小时前
过滤器与监听器学习
java·经验分享·笔记·学习
程序员小假2 小时前
我们来说一下 b+ 树与 b 树的区别
java·后端
Meepo_haha2 小时前
Spring Boot 条件注解:@ConditionalOnProperty 完全解析
java·spring boot·后端
sheji34163 小时前
【开题答辩全过程】以 基于springboot的房屋租赁系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
木井巳3 小时前
【递归算法】子集
java·算法·leetcode·决策树·深度优先
椎4953 小时前
Redis day02-应用-实战-黑马点评-短信登录
数据库·redis·spring