你看这个spring的aop它又大又宽
aop🚓
- AOP 分类
- AspectJ | 高级但是难用
- Spring AOP | 易用但仅支持方法
- aop 原理
明月几时有,把酒问青天。——唐代李白《将进酒》
AOP 分类
在 Spring Boot 中,AOP 的实现主要有以下几种:
-
基于 AspectJ 的 AOP:这是一种基于 Java 语言扩展(Java Language Extension,JLE)的 AOP 实现方式,支持静态织入和动态织入两种方式。
-
Spring AOP:这是 Spring 框架自带的 AOP 实现方式,基于动态代理机制实现,只支持方法级别的切面。
-
自定义注解实现 AOP:通过自定义注解和 AOP 技术实现业务逻辑和切面逻辑的分离,便于代码的维护和扩展。
其中,基于 AspectJ 的 AOP 功能最为强大,但使用难度较大;Spring AOP 简单易用,但功能有一定限制;自定义注解实现 AOP 灵活性较高,但需要自行实现 AOP 切面逻辑。在实际开发中,应根据项目需要选择合适的 AOP 实现方式。
Spring AOP 是基于代理的 AOP,而 AspectJ 是基于字节码的 AOP
Spring AOP 和 AspectJ 都是 Spring Framework 中的 AOP 实现方式。Spring AOP 是基于代理的 AOP,而 AspectJ 是基于字节码的 AOP。
在 Spring Boot 中,默认情况下使用的是 Spring AOP。如果需要使用 ,可以通过在启动类上添加 @EnableAspectJAutoProxy(proxyTargetClass = true) 注解来开启。
如果需要使用 AspectJ, 需要引入 AspectJ jar包
@EnableAspectJAutoProxy 不是用来开启 AspectJ 的吗
配置 @EnableAspectJAutoProxy, 不引入 AspectJ jar包的情况下就使用 Spring AOP
@EnableAspectJAutoProxy 注解可以用来开启 AspectJ 的支持,但是它也是用来开启 Spring AOP 的。
在 Spring 中,Spring AOP 和 AspectJ 都是实现 AOP 的方式之一。@EnableAspectJAutoProxy 注解用来开启 Spring AOP 的支持,如果在注解中设置 proxyTargetClass=true,则会使用 CGLIB 来创建代理对象,否则会使用 JDK 的动态代理。
当然,在 Spring Boot 中,如果需要使用 AspectJ,也可以在启动类上添加 @EnableAspectJAutoProxy(proxyTargetClass = true) 注解来开启 AspectJ 支持
AspectJ | 高级但是难用
AspectJ中的静态织入和动态织入
AspectJ 是一个基于 Java 语言的切面编程框架,它提供了两种切面织入方式:静态织入和动态织入。
静态织入是指在编译期间将切面代码织入到目标类中,生成一个新的字节码文件。在运行期间,JVM 加载这个字节码文件,并且这个字节码文件包含了目标类和切面代码,从而实现对目标类的增强。静态织入的优点是织入后的代码执行效率高,缺点是需要在编译期间进行织入,增加了额外的工作量和复杂度。
动态织入是指在运行期间将切面代码织入到目标类中,不需要在编译期间进行修改。在运行期间,通过 JVM 提供的动态代理技术或字节码生成技术,将切面代码织入到目标类中,从而实现对目标类的增强。动态织入的优点是织入更加灵活,可以在运行期间进行修改,缺点是织入后的代码执行效率相对较低。
在 AspectJ 中,静态织入和动态织入可以通过不同的方式实现。静态织入可以使用 AspectJ 编译器,将切面代码编译成字节码文件,并将其与目标类一起打包成一个 jar 包或 war 包,从而在运行期间加载这个包,实现对目标类的增强。动态织入可以使用 AspectJ 提供的 Runtime 织入功能,或者使用 Spring AOP 框架提供的动态代理技术,实现对目标类的增强。
AspectJ 支持更加灵活的切面编程,可以拦截不仅仅是方法级别的切面,还可以拦截字段、构造方法、类等级别的切面。
- 字段级别
要拦截字段级别的切面,可以使用 AspectJ 提供的 field 切点匹配器,例如:
javaCopy code
@Aspect
public class FieldAspect {@Before("get(* com.example.demo.model.User.name)")public void beforeFieldAccess(JoinPoint joinPoint) {// 拦截 User 类中的 name 字段的 getter 方法}}
在上面的示例中,使用 get 切点匹配器匹配 User 类中的 name 字段的 getter 方法,实现对字段级别的拦截。
- 构造方法级别
要拦截构造方法级别的切面,可以使用 AspectJ 提供的 initialization 切点匹配器,例如:
@Aspect
public class ConstructorAspect {@Before("execution(com.example.demo.model.User.new())")public void beforeConstructorExecution(JoinPoint joinPoint) {// 拦截 User 类的构造方法}}
在上面的示例中,使用 execution 切点匹配器匹配 User 类的构造方法,实现对构造方法级别的拦截。
- 类级别
要拦截类级别的切面,可以使用 AspectJ 提供的 type 切点匹配器,例如:
@Aspect
public class ClassAspect {@Before("execution(* com.example.demo.service.*.*(..)) && type(service)")public void beforeServiceMethodExecution(JoinPoint joinPoint) {// 拦截 com.example.demo.service 包下的所有方法,并且方法所属的类必须被 @Service 注解标注}}
在上面的示例中,使用 execution 切点匹配器匹配 com.example.demo.service 包下的所有方法,并且方法所属的类必须被 @Service 注解标注,实现对类级别的拦截。
需要注意的是,AspectJ 的切面匹配器比 Spring AOP 更加灵活,可以匹配更多的切点。但是,AspectJ 的使用需要在编译期间进行织入,因此相对来说也更加复杂和耗费资源。在实际使用中,需要根据实际需求选择使用 Spring AOP 还是 AspectJ。
使用 AspectJ, 要引入什么jar包
Spring Boot 默认使用 Spring AOP,如果要使用 AspectJ,需要手动引入 AspectJ 相关的依赖。
可以在 pom.xml 文件中添加以下依赖:
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.7</version>
</dependency>
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.9.7</version>
</dependency>
其中,aspectjweaver 依赖是必须的,它包含了 AspectJ 的运行时环境;aspectjrt 依赖是可选的,它包含了 AspectJ 的运行时库,如果使用了 AspectJ 的注解,建议添加该依赖。
在添加了依赖后,可以在启动类上添加 @EnableAspectJAutoProxy 注解开启 AspectJ 支持,或者在切面类上使用 @Aspect 注解定义切面类。
Spring AOP | 易用但仅支持方法
Spring AOP 只支持方法级别的切面
Spring AOP 只支持方法级别的切面指的是,Spring AOP 只能拦截方法的执行,而不能拦截其他级别的切面,例如字段级别、构造方法级别、类级别等。
这是因为 Spring AOP 的实现方式是基于 JDK 动态代理或 CGLIB 字节码生成技术的,而 JDK 动态代理和 CGLIB 都是基于方法级别的。在使用 JDK 动态代理时,代理对象必须实现一个或多个接口,而接口是方法集合的抽象,因此只能对接口中定义的方法进行拦截;在使用 CGLIB 字节码生成技术时,会生成一个新的类作为代理类,该类是原始类的子类,因此只能拦截原始类中的方法,无法拦截字段、构造方法等。
不过,Spring AOP 还提供了其他的一些拦截点,例如:
-
Bean 生命周期事件:可以在 Bean 初始化前后、销毁前后等事件中执行通知。
-
AspectJ 注解:可以使用 @AspectJ 注解来实现更为灵活的切面拦截,支持字段级别、构造方法级别、类级别等切入点。
需要注意的是,使用 AspectJ 注解时,需要添加相应的 AspectJ 依赖,并配置 AspectJ 编译器,以支持注解的解析和织入。
aop 原理
通过 @EnableAspectJAutoProxy 将aop的功能通过bean后置处理器, 关联到我们的IOC容器中

EnableAspectJAutoProxy 的目的是为了导入 AnnotationAwareAspectJAutoProxyCreator

AnnotationAwareAspectJAutoProxyCreator 又是bean后置处理器, 这不就挂钩上了吗
史上最完整的AOP底层原理_哔哩哔哩_bilibili
一文吃透spring aop底层原理_spring aop的底层原理_吴法刚的博客-CSDN博客
那么AOP具体是如何在我体内运行的呢?在我启动时会创建IOC容器, 同时将我体内的bean进行三个连续的动作,
-
构造
-
填充
-
属性初始化
AOP功能就是通过我体内一个专门处理AOP的bean后置处理器 DefaultAdvisorAutoProxyCreator 进行方法增强的,
可以算作IOC容器的附加功能, 所有的后置处理器都在bean构造完, 并且填充了属性之后执行
-
填充了属性之后执行
-
在每一个bean初始化之后都会调用这个后置处理器的postProcessorAfterInitialization 方法, 在这个方法里为需要使用AOP的bean创建代理对象。
-
先通过getAdvicesAndAdvisorsForBean方法, 获取所有的增强Advice, 同时判断当前bean是否满足我们配置的切面条件
如果满足条件的话, 就会为这个bean构造代理对象来实现AOP
为了更统一更方便的构造代理对象, 我会先搭建一个专门用来构造生产代理对象的工厂, proxyFactory, 我会告诉这个工厂具体选择哪种方式进行代理, 分别是cglib和jdkProxy。
通过添加@EnableAspectJAutoProxy注解, 并且将其中proxyTargetClass配置改为 true 强制使用cglib。
当然啦在spring boot中默认就是使用cglib, 不过只有这个配置为false, 同时该类实现了任意接口才会使用jdkProxy, 否则还是会使用cglib方式。
ProxyFactory知道使用哪种方式之后, 就会构造jdkDynamicAopProxy或者cglibAopProxy, 然后就可以通过他们的getProxy方法获得真正的代理对象。
jdkDynamicAopProxy
先说相对简单, 而且即将被我无情放弃的jdkDynamicAopProxy, 在getProxy中会构造一个实现同样bean接口的代理对象, 将真实bean作为代理, 对象中的一个成员变量。
在调用bean方法的时候就会执行代理对象中的 invoke 方法
这个 invoke 方法只有两步,
-
我会通过之前提到的execution表达式, 获取所有与该方法匹配的所有增强方法, 并将它们组成调用链同时进行排序
-
开始按顺序执行这些调用链, 这里的调用方式就是经典的责任链模式, 在调用中间会插入bean 执行bean真实的方法
cglibAopProxy
最为常用的cglibAopProxy, 同样会在getProxy方法中构造代理对象
用增强器 Enhancer 来设置代理基本信息以及增强方法的调用链
接着执行 Enhancer create方法来生成代理对象
和jdkDynamicAopProxy不同的是cglib是基于jdk rt jar包中的asm来生成一组新的class文件, 然后实例化它的对象, 所以对于没有实现接口的bean也可以生成代理对象
在调用bean方法的时候, 会先执行代理对象的intercept方法, 与jdkProxy一样, 也会通过责任链来执行所有的方法增强。
相关文章:
你看这个spring的aop它又大又宽
aop🚓AOP 分类AspectJ | 高级但是难用Spring AOP | 易用但仅支持方法aop 原理明月几时有,把酒问青天。——唐代李白《将进酒》 AOP 分类 在 Spring Boot 中,AOP 的实现主要有以下几种: 基于 AspectJ 的 AOP:这是一种基…...
设计模式-创建-单例模式
4.1.1 模式介绍 定义 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一,此模式保证某个类在运行期间,只有一个实例对外提供服务,而这个类被称为单例类。 作用 保证一个类只有一个实例为该实例提供一个全…...
使用mybatis-plus-generator配置一套适合你的CRUD
1、maven引入 mybatis-plus-generator 和模板引擎,你也可以使用freemarker之类的,看个人 <!-- mybatisplus代码生成器 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactI…...
MATLAB实现各种离散概率密度函数(概率密度/分布/逆概率分布函数)
MATLAB实现各种离散概率密度函数(概率密度/分布/逆概率分布函数) 1 常见离散概率分布的基本信息2 常见离散概率分布计算及MATLAB实现2.1 二项分布(Binomial Distribution)2.1.1 常用函数2.2 负二项分布(Negative Binomial Distribution)2.2.1 常用函数2.3 几何分布(Geom…...
指针的基本知识
我们不会用bit去表达一个数据,因为只能放0和1,能表达的数据太少了,内存地址最小单位是字节 11111111 0x0011 1字节8bit,8bit才算作一个地址,地址是以字节为最小单位&#…...
当你的IDE装上GPT
文章目录前言下载安装使用步骤前言 我们可能要从“CV”工程师变成“KL工程师了,为什么叫”KL“工程师呢, 因为只要K和L两个指令就可以直接生成代码、修改代码,哪行代码不会点哪里,他都给你解释得明明白白。 提示:以下…...
一图看懂 pathlib 模块:面向对象的文件系统路径, 资料整理+笔记(大全)
本文由 大侠(AhcaoZhu)原创,转载请声明。 链接: https://blog.csdn.net/Ahcao2008 一图看懂 pathlib 模块:面向对象的文件系统路径, 资料整理笔记(大全)摘要模块图类关系图模块全展开【pathlib】统计常量intbooltuple模块9 fnmatc…...
前端如何将node.js 和mongodb部署到linux服务器上
本文首发自掘金。 记录了我第一次成功部署node.js 和mongodb到linux服务器上了,期间也遇到一些小坑,但是网上各位大佬记录的文章帮了大忙,所以我也将过程记录了下来。 安装Node 使用nvm linux上安装node,肯定首选nvmÿ…...
mysql数据迁移
背景:随着时间的推移,交易系统中的订单表越来越大,目前达到500w数据。为了防止数据量过大导致的查询性能问题,现将订单表进行拆分,分为实时库和历史库。实时库保留近6个月的数据,用于退款业务需求ÿ…...
【4.3蓝桥备战】小朋友崇拜圈、正则问题
文章目录小朋友崇拜圈正则问题小朋友崇拜圈 小朋友崇拜圈 - 蓝桥云课 (lanqiao.cn) 拿到这道题要先把题目读懂。 下面的一行是表示:编号为i的小朋友,崇拜的对象为编号为path[i]的小朋友。 本题应该使用DFS,深度优先遍历找到可以成环的崇拜圈…...
MySQL读写分离中间件
1.什么是读写分离中间件? 就是实现当[写]的时候转发到主库,当[读]的时候转发到从库的工具。 很类似学习过的proxy,比如nginx proxy做动静分离. 2.为什么要实现读写分离? 1)让主库专注于写,因为读可以有很多从库可以干…...
【Spring源码设计模式】单例模式外带设计模式的单例模式
Bean的概念 是Spring框架在运行时管理的对象,是任何引用程序的基本构建块。 Bean的属性 id属性:Bean的唯一标志名,必须以字母开头且不包含特殊字符 class属性:用来定义类的全限定名(包名 类名) name属性…...
go并发编程 —— singleflight设计模式
什么是singleflight singleflight是一种并发编程设计模式,将同一时刻的多个并发请求合并成一个请求,以减少对下游服务的压力 为什么叫singleflight fly可以理解为请求数,singleflight就是单个请求 使用场景 该模式主要用于防止缓存击穿 …...
【LeetCode】二叉树的中序遍历(递归,迭代,Morris遍历)
目录 题目要求:给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。 方法一:递归 方法二:迭代 思路分析: 复杂度分析 代码展示: 方法三:Morris 遍历 思路分析: 复杂度分析…...
银行数字化转型导师坚鹏:数字化转型背景下的银行柜员提升之道
数字化转型背景下的银行柜员提升之道 课程背景: 很多银行都在开展银行数字化运营工作,目前存在以下问题急需解决: l 不清楚银行数字化运营包括哪些关键工作? l 不清楚银行数字化运营工作的核心方法论? l 不清楚银行数字…...
ChatGPT的平替来了?一文总结 ChatGPT 的开源平替,你值得拥有
文章目录【AIGC精选】总结 ChatGPT 的开源平替,你值得拥有1.斯坦福发布 Alpaca 7B,性能匹敌 GPT-3.52.弥补斯坦福 Alpaca 中文短板,中文大模型 BELLE 开源3.国产AI大模型 ChatGLM-6B 开启内测4.中文 Alpaca 模型 Luotuo 开源5. ChatGPT 最强竞…...
关于数据同步工具DataX部署
1.DataX简介 1.1 DataX概述 DataX 是阿里巴巴开源的一个异构数据源离线同步工具,致力于实现包括关系型数据库(MySQL、Oracle等)、HDFS、Hive、ODPS、HBase、FTP等各种异构数据源之间稳定高效的数据同步功能。 源码地址:GitHub - alibaba/DataX: DataX是…...
如何开发JetBrains插件
1 标题安装 IntelliJ IDEA 如果您还没有安装 IntelliJ IDEA,从官方网站下载并安装 IntelliJ IDEA Community Edition(免费)或 Ultimate Edition(付费)。 2 创建插件项目 在 IntelliJ IDEA 中,创建一个新…...
企业采购成本管理的难题及解决方案
企业采购成本控制是企业管理中的一个重要方面,也是一个不容易解决的难题。企业采购成本控制面临的难题包括以下几个方面: 1、采购流程复杂 企业采购通常需要经过一系列的流程,包括采购计划、采购申请、报价、比价、议标、合同签订、验收、付…...
龙蜥白皮书精选:基于 SM4 算法的文件加密(fscrypt)实践
文/张天佳 通常我们会以文件作为数据载体,使用磁盘,USB 闪存,SD 卡等存储介质进行数据存储,即便数据已经离线存储,仍然不能保证该存储介质不会丢失,如果丢失那么对于我们来说有可能是灾难性的事件。因此对…...
HarmonyOS6 半年磨一剑 - RcCheckbox 组件核心架构与类型系统设计
文章目录前言一、组件整体架构1.1 双组件协作设计1.2 文件结构1.3 装饰器分工二、类型系统深度解析2.1 值类型的宽泛设计2.2 选项配置接口2.3 形状与尺寸类型三、核心参数体系3.1 RcCheckbox 参数全览3.2 RcCheckboxGroup 扩展参数四、内部状态设计4.1 受控模式的双状态机制4.2…...
从“单点防御”到“全局联动”:手把手教你用EDR和NDR构建企业安全闭环
从“单点防御”到“全局联动”:手把手教你用EDR和NDR构建企业安全闭环 当企业的安全团队还在疲于应对零散的端点告警和网络流量异常时,攻击者早已开始采用自动化工具进行横向移动。传统孤立的防御手段就像用多个单点摄像头监控银行金库——每个摄像头都…...
如何通过智能求职助手提升职位时间筛选效率?揭秘高效求职新方法
如何通过智能求职助手提升职位时间筛选效率?揭秘高效求职新方法 【免费下载链接】boss-show-time 展示boss直聘岗位的发布时间 项目地址: https://gitcode.com/GitHub_Trending/bo/boss-show-time 在当今竞争激烈的就业市场中,职位时间筛选已成为…...
图深度学习文献宝库LiteratureDL4Graph:一站式掌握图神经网络研究进展
图深度学习文献宝库LiteratureDL4Graph:一站式掌握图神经网络研究进展 【免费下载链接】LiteratureDL4Graph 项目地址: https://gitcode.com/gh_mirrors/li/LiteratureDL4Graph 想要快速掌握图神经网络(GNN)和图深度学习的最新研究进展吗?Litera…...
如何用anyRTC-RTMP-OpenSource打造个性化直播数据源:自定义视频采集完整指南
如何用anyRTC-RTMP-OpenSource打造个性化直播数据源:自定义视频采集完整指南 【免费下载链接】anyRTC-RTMP-OpenSource RTMP 推流器,RTMP(HLS)秒开播放器,直播点播,跨平台(Win,IOS,Android)开源代码 项目…...
8人SolidWorks研发共享一台服务器——性能算力共享智能按需分配
8人SolidWorks研发团队可借助云飞云智能共享云桌面,通过以下方式实现一台服务器的性能算力共享与智能按需分配。一、核心硬件配置CPU:选择多核高主频处理器,如Intel Core i9 14900K(24核32线程)或AMD锐龙9 9950X&#…...
Asp.Net MVC杂谈之:—步步打造表单验证框架[重排版](1)
在实际使用中,我们可以考虑多种形式来进行这一验证(注:本文目前只研究服务器端验证的情况),最直接的方式莫过于对每个表单值手动用C#代码进行验证了,比如: if(!Int32.TryParse(Request.Form[“age”], out age)){ xxxx… } If(age < xxx || age > xxx){ xxxx… }…...
Delphi MVC框架ActiveRecord中间件多连接配置详细解析[特殊字符]
1. 数组长度必须一致1234567// 错误示例 - 会抛出异常TMVCActiveRecordMiddleware.Create(MainDB,[LogDB, CacheDB], // 2个元素[LogDB_Def], // 1个元素 ← 错误!MultiConnections.ini);2. 连接名命名规范1234567// 建议使用有意义的命…...
BACnet4j实战:从模拟设备到点位数据采集的完整流程解析
1. BACnet4j与工业物联网数据采集入门 第一次接触BACnet协议时,我被各种专业术语搞得晕头转向。直到用BACnet4j成功读取到第一个温度传感器的数据,才真正理解这个协议的价值。BACnet/IP就像工业设备间的普通话,而BACnet4j就是让Java程序能说这…...
MT5 Zero-Shot参数详解:Temperature与Top-P对中文改写多样性的影响
MT5 Zero-Shot参数详解:Temperature与Top-P对中文改写多样性的影响 1. 项目概述 MT5 Zero-Shot Chinese Text Augmentation 是一个基于 Streamlit 和阿里达摩院 mT5 模型构建的本地化 NLP 工具。这个工具专门用于中文句子的语义改写和数据增强,能够在保…...
