【SpringAOP】Spring AOP 底层逻辑:切点表达式与原理简明阐述
前言
🌟🌟本期讲解关于spring aop的切面表达式和自身实现原理介绍~~~
🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客
🔥 你的点赞就是小编不断更新的最大动力
🎆那么废话不多说直接开整吧~~
目录
📚️1.切点表达式
🚀1.1execution表达式
🚀1.2@annotation
1.自定义注解
2.切面类
3.添加注解
📚️2.Spring AOP原理
🚀2.1代理模式
1.静态代理(了解)
2.动态代理(八股)
🚀2.2Spring AOP原理总结
📚️3.总结
📚️1.切点表达式
我们在上一期了解到了关于通知中切点表达式execution表达式,但是没有做很详细的介绍,不仅如此在切点表达式中,有两种方式,下面来一一介绍
🚀1.1execution表达式
切点表达式的结构如下所示:
execution(<访问修饰符> <返回类型> <包名.类名.⽅法(⽅法参数)> <异常>)
而在我们上期写的表达式中格式如下:
@Around("execution(* com.example.springaop.controller.*.*(..))")
解释:
* :匹配任意字符,只匹配⼀个元素(返回类型, 包, 类名, ⽅法或者⽅法参数)
.. :匹配多个连续的任意符号, 可以通配任意层级的包, 或任意类型, 任意个数的参数
上述的controller后的两个 * 代表就是每一层,括号里的 .. 就是表示任意的方法参数;这里也可以代表无参数;
举例:
execution(public String com.example.demo.controller.TestController.t1())
解释:testcontroller类下的名为t1的方法,并且这里的方法是无参的,访问修饰符可以省去;
execution(* com.example.demo.controller.TestController.t1())
解释:这里可以访问的就是没有任何限制的访问权限,匹配所有返回类型;
execution(* com.example.demo.controller.TestController.*())
解释:这里匹配所有的方法,这些方法是无参的;
execution(* com.example.demo.controller.*.*(..))
解释:这里匹配controller包下所有类的所有方法
execution(* com..TestController.*(..))
解释:这里匹配com包下的所有testcontroller类的所有方法
🚀1.2@annotation
我们在上述的简述中了解到,关于execution表达式如何作用于匹配某个方法和类,但是当存在两个类,都要进行匹配,并且里面的方法也是无规则的,那如何呢,此时就要@annotation进行操作了;
假如有以下的两个控制类:
@RestController
@RequestMapping("/test")
public class TestController {@RequestMapping("/t1")public String test1(){log.info("这是t1执行");return "t1";}@RequestMapping("/t2")public String test2(){log.info("这是t2在执行");return "t2";}
}
@RestController
@RequestMapping("/user")
public class UserController {@RequestMapping("/u1")public String user1(){return "u1";}@RequestMapping("/u2")public String user2(){return "u2";}
}
那么此时我们要将第一个控制器类的第一个方法进行匹配,以及第二个控制器类的方法进行匹配,那么此时的操作就是如下所示:
1.自定义注解
代码如下所示:
//定义自己的注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAspect {
}
@Target 标识了 Annotation 所修饰的对象范围, 即该注解可以⽤在什么地⽅.
@Retention 指Annotation被保留的时间⻓短, 标明注解的⽣命周期
2.切面类
使⽤ @annotation 切点表达式定义切点, 只对 @MyAspect ⽣效
代码如下所示:
@Aspect
@Component
@Slf4j
public class MyAnnotationAspect {@Before("@annotation(com.example.springaop.config.MyAspect)")public void doBefore(){log.info("before start...");}@After("@annotation(com.example.springaop.config.MyAspect)")public void doAfter(){log.info("after start...");}
}
这里小编设置了两种通知类,第一种是在目标方法执行前进行执行,第二种通知是在方法执行后进行执行,当然表达式里的的是我们自己注解的全限定路径,加上我们的定义注解名称;
3.添加注解
代码如下所示:
@MyAspect@RequestMapping("/t1")public String test1(){log.info("这是t1执行");return "t1";}
这是第一个类的第一个方法;
@MyAspect@RequestMapping("/u2")public String user2(){return "u2";}
这是第二个类的第二个方法;
此时就与这两个方法进行了匹配,那么就可执行切面通知了;
📚️2.Spring AOP原理
🚀2.1代理模式
代理模式也叫委托模式定义:为其他对象提供⼀种代理以控制对这个对象的访问. 它的作⽤就是通过提供⼀个代理类, 让我们在调⽤⽬标⽅法的时候, 不再是直接对⽬标⽅法进⾏调⽤, ⽽是通过代理类间接调⽤(其实就是中介的作用)
1. Subject: 业务接⼝类. 可以是抽象类或者接⼝(不⼀定有)
2. RealSubject: 业务实现类. 具体的业务执⾏, 也就是被代理对象.(真正的房东)
3. Proxy: 代理类. RealSubject的代理 (中介)
这里的代理模式分为两种
• 静态代理: 由程序员创建代理类或特定⼯具⾃动⽣成源代码再对其编译, 在程序运⾏前代理类的
.class ⽂件就已经存在了.
• 动态代理: 在程序运⾏时, 运⽤反射机制动态创建⽽成
1.静态代理(了解)
代码如下:
定义一个subject业务接口;
public interface SubjectHouse {void rentHouse();
}
让代理对象继承这个接口,并写出要代理什么
public class RealSubjectHouse implements SubjectHouse{//真正的房东@Overridepublic void rentHouse(){System.out.println("我是房东,我要出租房子");}
}
最后中介,进行代理
public class HouseProxy implements SubjectHouse{private SubjectHouse subjectHouse;public HouseProxy(SubjectHouse subjectHouse) {this.subjectHouse = subjectHouse;}@Overridepublic void rentHouse() {System.out.println("我是中介开始代理");subjectHouse.rentHouse();System.out.println("我是中介结束代理");}
}
解释这里使用了一个向上转型的思想,这里实际指定就是代理的对象就是realsubjecthouse(即真正的房东);
从上述代码可以看出, 我们修改接⼝(Subject)和业务实现类(RealSubject)时, 还需要修改代理类
(Proxy).
同样的, 如果有新增接⼝(Subject)和业务实现类(RealSubject), 也需要对每⼀个业务实现类新增代理类(Proxy).
2.动态代理(八股)
相⽐于静态代理来说,动态代理更加灵活.
我们不需要针对每个⽬标对象都单独创建⼀个代理对象, ⽽是把这个创建代理对象的⼯作推迟到程序运
⾏时由JVM来实现. 也就是说动态代理在程序运⾏时, 根据需要动态创建⽣成
这里的动态代理分为两种
JDK动态代理;
CGLIB动态代理;
JDK动态代理代码(了解)
public class JDKInvocationHandler implements InvocationHandler {private Object target;//目标对象public JDKInvocationHandler(Object target) {this.target = target;}/*** 代理对象 通过 invoke调用 目标对象的方法*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("我是代理, 开始代理");//通过反射, 调用目标对象的方法Object result = method.invoke(target, args);System.out.println("我是代理, 结束代理");return result;}
}
进行main方法调用:
SubjectHouse proxy= (SubjectHouse) Proxy.newProxyInstance(SubjectHouse .class.getClassLoader(),new Class[]{SubjectHouse .class},new JDKInvocationHandler(target));proxy.rentHouse();
newProxyInstance() , 这个⽅法主要⽤来⽣成⼀个代理对象
Loader: 类加载器, ⽤于加载代理对象.
interfaces : 被代理类实现的⼀些接⼝(这个参数的定义, 也决定了JDK动态代理只能代理实现了接⼝的⼀些类)
h : 实现了 InvocationHandler 接⼝的对象,target被代理对象
CGLIB动态代理代码
添加依赖:
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>
public class CGLibMethodInterceptor implements MethodInterceptor {private Object target;public CGLibMethodInterceptor(Object target) {this.target = target;}/*** 调用代理对象的方法*/@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("我是中介, 开始代理");Object result = method.invoke(target, args);System.out.println("我是中介, 结束代理");return result;}
}
最后进行调用:
SubjectHouse houseSubject = (SubjectHouse) Enhancer.create(target.getClass(), new CGLibMethodInterceptor(target));houseSubject.rentHouse();
上述存在一个比较重要的知识点:
JDK动态代理存在一个致命的问题,即只能代理接口,不能代理类,而CGLIB既可以代理接口,又可以代理类;
🚀2.2Spring AOP原理总结
spring AOP原理,是要从源码进行解读的,但是源码过于复杂,最终的情况就是如下所示:
在源码中的代理⼯⼚有⼀个重要的属性: proxyTargetClass, 默认值为false. 也可以通过程序设置(这里的默认值是根据不同情况来进行定义的)
大致意思就是在 proxyTargetClass为false时,在实现接口时使用JDK代理,只实现类的情况下,使用CGLIB代理,若proxyTargetClass,为true,那么所有实现方式都使用CGLIB代理;
Spring默认使用的的proxyTargetClass为false,但是在spring boot2.x之后proxyTargetClass默认为true,使用CGLIB进行代理;
当然我们可以使用配置项进行配置
spring.aop.proxy-target-class=false
这里设置proxyTargetClass默认为false;
📚️3.总结
本期主要讲解了关于切点表达式的两种表达方式,以及Spring AOP实现原理的两种代理模式,即JDK代理,以及CGLIB代理,最后进行Spring AOP原理的总结;
🌅🌅🌅~~~~最后希望与诸君共勉,共同进步!!!
💪💪💪以上就是本期内容了, 感兴趣的话,就关注小编吧。
😊😊 期待你的关注~~~
相关文章:

【SpringAOP】Spring AOP 底层逻辑:切点表达式与原理简明阐述
前言 🌟🌟本期讲解关于spring aop的切面表达式和自身实现原理介绍~~~ 🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客 🔥 你的点赞就是小编不断更新的最大动力 &am…...

HTTP-响应协议
HTTP的响应过程? 浏览器请求数据--》web服务器过程:请求过程 web服务器将响应数据-》到浏览器:响应过程 响应数据有哪些内容? 1.和请求数据类似。 2. 响应体中存储着web服务器返回给浏览器的响应数据。并且注意响应头和响应体之间…...
SQL进阶实战技巧:即时订单比例问题
目录 0 需求描述 1 数据准备 2 问题分析 3 小结 往期精彩 0 需求描述 订单配送中,如果期望配送日期和下单日期相同,称为即时订单,如果期望配送日期和下单日期不同,称为计划订单。 请从配送信息表(delivery_info)中求出每个用户的首单(用户的第一个订单)中即时订单…...
什么是端口
端口是用来区分同一网络设备(IP地址)上运行的不同服务或应用程序接收外部数据的窗口。 以下是几个要点: 对于我们发送请求指定的url中的端口,指的是对方服务器的用于接收数据的端口,如http的80端口,服务器通常都会设定要监听来自…...
【Flutter】使用ScrollController配合EasyRefresh实现列表预加载:在还未滑动到底部时加载下一页数据
需求/背景 在我们的业务场景中,列表的加载使用easy_refresh组件: https://pub.dev/packages/easy_refresh 大概效果是往上滑动到一定的offset会触发一个上滑加载,可以触发一些网络请求拉取列表后面的数据来展示。 这种模式一般在一页翻完…...
【2025 Rust学习 --- 11 实用工具特型01】
清理特型Drop 当一个值的拥有者消失时,Rust 会丢弃(drop)该值。丢弃一个值就必须释放 该值拥有的任何其他值、堆存储和系统资源。 丢弃可能发生在多种情况下: 当变量超出作用域时;在表达式语句的末尾;当…...
网络安全基础以及概念
1. 安全领域的概念 1.1 网络产品 1. EDR:终端检测与响应(Endpoint Detection and Response),终端主要包括我们的笔记本、台式机、手机、服务器等,EDR是一种运行在终端上安全软件,主要负责监控网络流量、可疑进程、注册表活动等其他安全相关的事件与活动。当发现有威胁是自…...

windows和linux的抓包方式
1.实验准备: 一台windows主机,一台linux主机 wireshark使用: 打开wireshark,这些有波动的就代表可以有流量经过该网卡,选择一张有流量经过的网卡 可以看到很多的流量,然后可以使用过滤器来过滤想要的流量…...

【Uniapp-Vue3】v-if条件渲染及v-show的选择对比
如果我们想让元素根据响应式变量的值进行显示或隐藏可以使用v-if或v-show 一、v-show 另一种控制显示的方法就是使用v-show,使用方法和v-if一样,为true显示,为false则不显示。 二、v-if v-if除了可以像v-show一样单独使用外,还…...
宝塔面板使用 GoAccess Web 日志分析教程
宝塔面板是一个简单方便的服务器运维面板,但其网站统计功能是收费的。而 GoAccess 是一个用 C 编写的免费开源 Web日志分析器,本文将介绍如何在宝塔面板中开启 GoAccess Web 日志分析功能。 内容索引 下载安装 GoAccess在宝塔面板中添加日志切割的计划任务将 Web 日志输出到…...

Windows 安装 Docker 和 Docker Compose
🚀 作者主页: 有来技术 🔥 开源项目: youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template 🌺 仓库主页: GitCode︱ Gitee ︱ Github 💖 欢迎点赞 👍 收藏 ⭐评论 …...
arcgis中用python脚本批量给多个要素类的相同字段赋值
1、python脚本 import arcpy# 设置工作空间路径 arcpy.env.workspace = r"D:\test.gdb"# 要素集名称 feature_dataset = "test"# 线要素类名称列表,初始化为空 line_feature_classes = []# 遍历要素集获取所有线要素类 for fc in arcpy.ListFeatureClass…...

目标客户营销(ABM)结合开源AI智能名片2+1链动模式S2B2C商城小程序的策略与实践
摘要:在数字化营销日益盛行的今天,目标客户营销(Account Based Marketing, ABM)作为一种高度定制化的营销策略,正逐步成为企业获取高质量客户、提升市场竞争力的重要手段。与此同时,开源AI智能名片21链动模…...

《异步编程之美》— 全栈修仙《Java 8 CompletableFuture 对比 ES6 Promise 以及Spring @Async》
哈喽,大家好!在平常开发过程中会遇到许多意想不到的坑,本篇文章就记录在开发过程中遇到一些常见的问题,看了许多博主的异步编程,我只能说一言难尽。本文详细的讲解了异步编程之美,是不可多得的好文…...
新模型设计:Hybrid Quantum-Classical Neural Network (HQCNN) for Image Classification
新模型设计:Hybrid Quantum-Classical Neural Network (HQCNN) for Image Classification 目录 新模型设计:Hybrid Quantum-Classical Neural Network (HQCNN) for Image Classification引言1. Hybrid Quantum-Classical Neural Network 简介2. Hybrid Quantum-Classical Neu…...

iOS 中spring动画的使用
我们先来看以下两个动画的效果 上面的位移动画,一个是普通的动画,一个是spring动画,可以明显的看出来,spring动画在动画的前期更快一些,给人的感觉干脆,利落 以下是代码 - (void)normalAnimation {[UIV…...

初学stm32 --- DMA直接存储器
目录 DMA介绍 STM32F1 DMA框图 DMA处理过程 DMA通道 DMA优先级 DMA相关寄存器介绍 F1 DMA通道x配置寄存器(DMA_CCRx) DMA中断状态寄存器(DMA_ISR) DMA中断标志清除寄存器(DMA_IFCR) DMA通道x传输…...
校医院挂号及预约 APP 的设计与实现
标题:校医院挂号及预约 APP 的设计与实现 内容:1.摘要 随着移动互联网的发展,越来越多的人开始使用手机应用程序来解决生活中的各种问题。本项目旨在设计和实现一款校医院挂号及预约 APP,以提高校医院的服务效率和质量,方便师生就医。本文介…...
代理模式详解与应用
代理模式(Proxy Pattern),也称为委托模式或 surrogate 模式,是一种结构型设计模式。它为其他对象提供一个代理以控制对这个对象的访问。通过引入代理对象,可以在不改变原始对象接口的前提下,添加额外的功能…...

Model-based RL自动出价算法的演进之路
▐ 导读 近年来,强化学习自动出价算法已成为智能投放领域的标志性技术,然而其所存在的在离线不一致、线上数据覆盖空间受限等关键问题尚未被完全解决。在本文中,我们提出一种Model-based RL(MBRL)自动出价算法训练新范…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...

均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...

10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...

针对药品仓库的效期管理问题,如何利用WMS系统“破局”
案例: 某医药分销企业,主要经营各类药品的批发与零售。由于药品的特殊性,效期管理至关重要,但该企业一直面临效期问题的困扰。在未使用WMS系统之前,其药品入库、存储、出库等环节的效期管理主要依赖人工记录与检查。库…...
数据库——redis
一、Redis 介绍 1. 概述 Redis(Remote Dictionary Server)是一个开源的、高性能的内存键值数据库系统,具有以下核心特点: 内存存储架构:数据主要存储在内存中,提供微秒级的读写响应 多数据结构支持&…...