Spring AOP通俗易懂的各种术语
创始人
2025-05-29 07:30:47

目录

基础概念

Spring AOP 通知类型

AOP联盟定义的通知类型

AspectJ定义的通知类型

面试题 

讲一下spring中的AOP

讲一下如可控制切面的执行顺序

讲一下jdk动态代理和Cglib动态代理的对比


基础概念

实例代码,可以先不看

package com.scm.myblog.aop;import com.scm.myblog.utils.CharsetFilterUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;@Aspect
@Component
public class CharsetAspect {//定义字符过滤切点@Pointcut("execution(* com.scm.myblog.controller.ArticleController.getArticleDetail(..))")public void CharSetPoint(){}//字符过滤环绕切面@Around("CharSetPoint()")public Object CharsetAspects(ProceedingJoinPoint pjp){//获取所有请求参数Object[] args = pjp.getArgs();//过滤请求参数args[0]= CharsetFilterUtils.tranCharset((String) args[0]);//将结果放回pjpObject o;try {o= pjp.proceed(args);} catch (Throwable e) {throw new RuntimeException(e);}//返回改变后的objectreturn o;}
}
 @ApiOperation("模糊查询加分页获取文章数据")@PostMapping("/getPageData")public Result getArticleByPageAndSearch(@RequestBody PageDto pageData) {return articleService.getArticlePage(pageData,false);}@ApiOperation("获取详细文章内容")@GetMapping("/getArticles/{title}")public Result getArticleDetail(@PathVariable("title") String title, HttpServletRequest request) {//将文章标题放在session中备用WebUtils.setValBySession(request,"title",title);return articleService.getArticleData(title);}/*** 获取文章归档**/@ApiOperation("根据时间线获取文章")@GetMapping ("/getArticlesByTimeLine")public Result getArticlesByTimeLine(){return articleService.getArticlesByTimeLine();}

连接点:因为Spring只支持方法执行作为连接点,所有在spring中的连接点就是满足条件的各个方法。看如下的图中的箭头中指向的方法即是连接点。

 

切点:切点就是我们配置的满足我们条件的目标方法。切点一定是连接点。它是连接点位置的具体化就是了,看图。

我们通过切点表达式配置了一个具体的连接点(getArticleDetail(..)),它是一个具体的方法,可以对比上上图中的连接点,加深理解。

通知/增强(Advice: 就是我们编写的通过Aop去实现代码增强的方法。看图即可,图中的方框中即是一个通知,它通过@Around实现了对切点处的方法的增强。

 


切面:切面是切点和通知的组合称谓,就是变相给组合起了个名字,还是看图即可,方框中的就是一个切面。

 注意的是一个类中可能会有多个切面的。比如看代码即可。

我的代码中就出现了5个切面的。

package com.scm.myblog.aop;import com.scm.myblog.entity.Comment;
import com.scm.myblog.entity.VO.Result;
import com.scm.myblog.serviceUtils.AdminBlogUtils;
import com.scm.myblog.serviceUtils.RedisServiceBox;
import com.scm.myblog.serviceUtils.UserBlogUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;import java.util.Arrays;
import java.util.List;/*** web数据记录AOP** @author Lancer* @date 2022/12/09*/
@Aspect
@Component
@Slf4j
public class WebDataRecordAspect {@Autowiredpublic RedisTemplate rs;//设置浏览量增加切点@Pointcut("execution(public * com.scm.myblog.controller.ArticleController.getArticleDetail(..))")public void ViewAddPointcut() {}//设置文章增加切点@Pointcut("execution(public * com.scm.myblog.controller.AdminArticleController.addArticles(..))")public void AddArticlePointcut() {}//设置文章减少切点@Pointcut("execution(public * com.scm.myblog.controller.AdminArticleController.removeArticles(..))")public void RemoveArticlePointcut() {}//设置评论增加切点@Pointcut("execution(public * com.scm.myblog.controller.CommentController.setComment(..))")public void AddCommentPointcut() {}//设置评论减少切点@Pointcut("execution(public * com.scm.myblog.controller.AdminCommentController.removeComment(..))")public void RemoveCommentPointcut() {}/*** 浏览量增加切面** @param j j*/@Before("ViewAddPointcut()")public void ViewAdd(JoinPoint j){String sendTitle="";Object[] args = j.getArgs();if (args != null) {sendTitle=(String)args[0];}RedisServiceBox.addViewCount(sendTitle);log.info(sendTitle+"浏览加1");}//文章DP增加到redis@AfterReturning(pointcut ="AddArticlePointcut()",returning = "r")public void AddArticle(Object r){//获取方法返回值Object data=getResultData(r);if(data!=null){String title=(String)data;//增加根据文章的点赞数据到redisRedisServiceBox.addDataToRedis(title);log.info("新增文章成功!文章标题为 "+title);}}//文章DP减少redis@AfterReturning(pointcut ="RemoveArticlePointcut()",returning = "r")public void RemoveArticle(Object r){//获取方法返回值Object data=getResultData(r);if(data!=null){Long[] ids=(Long[])data;//删除文章的点赞数据在redisRedisServiceBox.deleteBatchDataToRedis(ids);log.info("删除文章成功!文章id为 "+ Arrays.toString(ids));}}//评论量增加在redis@AfterReturning(pointcut ="AddCommentPointcut()",returning = "r")public void AddComment(Object r){//获取方法返回值Object data=getResultData(r);if(data!=null){String title=(String)data;//更新Redis中的文章数据RedisServiceBox.addCommentCount(title);log.info("评论增加成功!文章标题为 "+title);}}//评论量减少在redis@AfterReturning(pointcut ="RemoveCommentPointcut()",returning = "r")public void RemoveComment(Object r){//获取方法返回值Object data=getResultData(r);if(data!=null){List commentList = (List) (data);List ids = AdminBlogUtils.getArticleIdByCommentList(commentList);//更新Redis中的文章数据RedisServiceBox.removeCommentCount(ids);log.info("评论删除成功!文章id为"+ids);}}public Object getResultData(Object r){//获取方法返回值Result r1 = (Result) r;return r1.getData();}
}

织入(Weaving):织入是一个过程,是将切面应用到目标对象从而创建出AOP代理对象的过程,织入可以在编译期、类装载期、运行期进行。也是创建AOP代理对象的过程。

Spring AOP 通知类型

AOP联盟定义的通知类型

通知类型接口描述
前置通知 org.springframework.aop.MethodBeforeAdvice在目标方法执行前实施增强。
后置通知org.springframework.aop.AfterAdvice在目标方法执行后实施增强。
后置返回通知org.springframework.aop.AfterReturningAdvice在目标方法执行完成,并返回一个返回值后实施增强。
环绕通知org.aopalliance.intercept.MethodInterceptor在目标方法执行前后实施增强。
异常通知org.springframework.aop.ThrowsAdvice在方法抛出异常后实施增强。
引入通知org.springframework.aop.IntroductionInterceptor在目标类中添加一些新的方法和属性。

AspectJ定义的通知类型

Before 前置通知:目标对象的方法调用之前触发
After 后置通知:目标对象的方法调用之后触发
AfterReturning 返回通知:目标对象的方法调用完成,在返回结果值之后触发
AfterThrowing 异常通知:目标对象的方法运行中抛出 / 触发异常后触发
注意一点,AfterReturning 与 AfterThrowing 两者是互斥的!如果方法调用成功无异常,则会有返回值;如果方法抛出了异常,则不会有返回值。
Around 环绕通知:编程式控制目标对象的方法调用。环绕通知是所有通知类型中可操作范围最大的一种,因为它可以直接拿到目标对象,以及要执行的方法,所以环绕通知可以任意的在目标对象的方法调用前后搞事,甚至不调用目标对象的方法
 

面试题 

讲一下spring中的AOP

AOP 即面向切面编程,全称 Aspect Oriented Programming ,它是 OOP 的补充。OOP 关注的核心是对象,AOP 的核心是切面(Aspect)。AOP 可以在不修改功能代码本身的前提下,使用运行时动态代理的技术对已有代码逻辑增强。AOP 可以实现组件化、可插拔式的功能扩展,通过简单配置即可将功能增强到指定的切入点。在开发中我常使用的是AspectJ提供的通知类型,实现代码的增强的,然后AOP 的使用范围还是非常广的比如
1 业务日志切面:可以记录业务方法调用的痕迹
2 事务控制:通过切面可以声明式控制事务
3 权限校验:执行方法之前先校验当前登录用户是否有权调用
4 数据缓存:执行方法之前先从缓存中取,取到则直接返回不走业务方法。

讲一下如可控制切面的执行顺序

1 显式使用 @Order 注解,或者 Ordered 接口,声明切面的执行顺序(默认 Integer.MAX_VALUE ),即值越小的先执行,值越大的后执行,同时先执行的会后结束
2  通过使用类名的 unicode 编码顺序,控制切面的执行顺序,unicode越小的越先执行的

讲一下jdk动态代理和Cglib动态代理的对比


jdk 动态代理要求被代理的对象所属类至少实现一个接口,它是 jdk 内置的机制
Cglib 动态代理无此限制,使用字节码增强技术实现,需要依赖第三方 Cglib 包
jdk 动态代理的代理对象创建速度快,执行速度慢;

Cglib 动态代理的代理对象创建速度慢,执行速度快
 

相关内容

热门资讯

数字操作方法 系列文章目录 前端系列文章——传送门 JavaScript系列文章——传送门 文章目录系列文章目录...
Cartesi 2023 年 ... 查看 Cartesi Machine、Cartesi Rollups 和 Noether 的更新正在...
JavaWeb——jsp概述入... JSP定义:  在如下一个jsp文件里面有如下的代码  <%@ page content...
一切喜怒哀乐都来自于你的认知 01 有个学子,准备出国,父母请来清华的教授宁向东。请问教授࿱...
JAVA并发编程——synch... 引言         Java语言为了解决并发编程中存在的原子性、可见性和有序性问题,...
git学习----3.21 未... 文章目录前言Git :一个分布式版本控制工具目标一、概述1.1 开发中的实际场景1.2...
Qt优秀开源项目之十七:QtP... QtPromise是Promises/A+规范的Qt/C++实现。该规范的译...
【前端八股文】JavaScri... 文章目录Set概念与arr的比较属性和方法并集、交集、差集Map概念属性和方法String用索引值和...
海康硬盘录像机接入RTSP/o... EasyNVR安防视频云服务平台可支持设备通过RTSP/Onvif协议接入平台,能提供...
在混合劳动力时代如何避免网络安... 在混合劳动力时代如何避免安全网络风险 三年多来,混合工作一直是工作生活中不可或缺的一...
2023还不懂Jmeter接口... 这里介绍的Jmeter接口测试的的实战,如果文章内容没遇看懂的话,我这边...
基于4G/5G弱网聚合的多链路... 基于4G/5G多卡聚合(弱网聚合)的智能融合通信设备技术亮点 增强带宽提供可靠连接 通过将多个有线和...
如何使用Synplify综合v... 文章目录使用Synplify综合的好处synplify的教程方法1(无效)...
2023年全国最新高校辅导员精... 百分百题库提供高校辅导员考试试题、辅导员考试预测题、高校辅导员考试真题、辅导员证考试题库等ÿ...
2022年18个值得期待的Le... 有数百个独特的LearnDash附加组件,您可能很难选择您的LearnDash LMS...
【java基础】Stream流... 文章目录基本介绍流的创建流的各种常见操作forEach方法filter方法map方法peek方法fl...
javaweb高校行政办公自动... 本课题基于我国高校管理信息化建设现状,结合在实际工作中所遇到的问题和收获,...
一款专门为自动化测试打造的集成... 你好,我是不二。 随着行业内卷越来越严重,自动化测试已成为测试工程师的...
【go-zero】golang... 一、casbin 概览 1、casbin基本了解 casbin的GitHub:https://git...
现在开发低代码平台算晚吗? 现在开发低代码平台算晚吗?作为低代码的亲戚——零代码厂商,这篇就以“厂商...
【JavaWeb】书城项目(2... 222.书城项目-第三阶段:修改所有html页面为jsp页面 改成jsp页面之后&#x...
基于jeecgboot的大屏设...      通过前面设计好数据源后,就要进行数据集的设计了。      一、还是在onl...
Linux命令小技巧:显示文件... 工作中会有很多千奇百怪的需求,比如:如何在 Linux 命令行中快速找到...
【找工作】-- 大数据工程师找... 目录 1.前言 2.找工作的理论知识 2.1 分析个人特征 2.1.1 你自身优势是什么?
C++基础算法④——排序算法(... 排序算法 1.插入排序 2.桶排序 1.插入排序 基本思想:将初始数据分为有序部分和...
nginx快速入门.跟学B站n... nginx快速入门.跟学B站nginx一小时精讲课程笔记nginx简介及环境准备nginx简介环境准...
ORACLE存过互相调用之间事... 今天在问答区看到一个问题是 假如有procedureA、procedureB和procedureC&...
基于java中Springbo... 基于java中Springboot框影视影院订票选座管理系统 开发语言:Java 框...
CVE-2018-18086 最近闲来无事,看到青少年CTF平台,感觉对新手还是比较友好的࿰...
【深度学习】基于Hough变化... 💥💥💞💞欢迎来到本博客❤️❤️&#x...