当前位置: 首页 > news >正文

你看这个spring的aop它又大又宽

aop🚓

        • AOP 分类
        • AspectJ | 高级但是难用
        • Spring AOP | 易用但仅支持方法
        • aop 原理

明月几时有,把酒问青天。——唐代李白《将进酒》

AOP 分类

在 Spring Boot 中,AOP 的实现主要有以下几种:

  1. 基于 AspectJ 的 AOP:这是一种基于 Java 语言扩展(Java Language Extension,JLE)的 AOP 实现方式,支持静态织入和动态织入两种方式。

  2. Spring AOP:这是 Spring 框架自带的 AOP 实现方式,基于动态代理机制实现,只支持方法级别的切面。

  3. 自定义注解实现 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 支持更加灵活的切面编程,可以拦截不仅仅是方法级别的切面,还可以拦截字段、构造方法、类等级别的切面。

  1. 字段级别

要拦截字段级别的切面,可以使用 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 方法,实现对字段级别的拦截。

  1. 构造方法级别

要拦截构造方法级别的切面,可以使用 AspectJ 提供的 initialization 切点匹配器,例如:

@Aspect
public class ConstructorAspect {@Before("execution(com.example.demo.model.User.new())")public void beforeConstructorExecution(JoinPoint joinPoint) {// 拦截 User 类的构造方法}}

在上面的示例中,使用 execution 切点匹配器匹配 User 类的构造方法,实现对构造方法级别的拦截。

  1. 类级别

要拦截类级别的切面,可以使用 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 还提供了其他的一些拦截点,例如:

  1. Bean 生命周期事件:可以在 Bean 初始化前后、销毁前后等事件中执行通知。

  2. AspectJ 注解:可以使用 @AspectJ 注解来实现更为灵活的切面拦截,支持字段级别、构造方法级别、类级别等切入点。

需要注意的是,使用 AspectJ 注解时,需要添加相应的 AspectJ 依赖,并配置 AspectJ 编译器,以支持注解的解析和织入。

aop 原理

通过 @EnableAspectJAutoProxy 将aop的功能通过bean后置处理器, 关联到我们的IOC容器中

EnableAspectJAutoProxy 的目的是为了导入 AnnotationAwareAspectJAutoProxyCreator

AnnotationAwareAspectJAutoProxyCreator 又是bean后置处理器, 这不就挂钩上了吗

史上最完整的AOP底层原理_哔哩哔哩_bilibili

一文吃透spring aop底层原理_spring aop的底层原理_吴法刚的博客-CSDN博客

那么AOP具体是如何在我体内运行的呢?在我启动时会创建IOC容器, 同时将我体内的bean进行三个连续的动作,

  1. 构造

  2. 填充

  3. 属性初始化

AOP功能就是通过我体内一个专门处理AOP的bean后置处理器 DefaultAdvisorAutoProxyCreator 进行方法增强的,

可以算作IOC容器的附加功能, 所有的后置处理器都在bean构造完, 并且填充了属性之后执行

  1. 填充了属性之后执行

  2. 在每一个bean初始化之后都会调用这个后置处理器的postProcessorAfterInitialization 方法, 在这个方法里为需要使用AOP的bean创建代理对象

  3. 先通过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 方法只有两步,

  1. 我会通过之前提到的execution表达式, 获取所有与该方法匹配的所有增强方法, 并将它们组成调用链同时进行排序

  2. 开始按顺序执行这些调用链, 这里的调用方式就是经典的责任链模式, 在调用中间会插入bean 执行bean真实的方法

cglibAopProxy

最为常用的cglibAopProxy, 同样会在getProxy方法中构造代理对象

用增强器 Enhancer 来设置代理基本信息以及增强方法的调用链
接着执行 Enhancer create方法来生成代理对象

和jdkDynamicAopProxy不同的是cglib是基于jdk rt jar包中的asm来生成一组新的class文件, 然后实例化它的对象, 所以对于没有实现接口的bean也可以生成代理对象

在调用bean方法的时候, 会先执行代理对象的intercept方法, 与jdkProxy一样, 也会通过责任链来执行所有的方法增强。

相关文章:

你看这个spring的aop它又大又宽

aop&#x1f693;AOP 分类AspectJ | 高级但是难用Spring AOP | 易用但仅支持方法aop 原理明月几时有&#xff0c;把酒问青天。——唐代李白《将进酒》 AOP 分类 在 Spring Boot 中&#xff0c;AOP 的实现主要有以下几种&#xff1a; 基于 AspectJ 的 AOP&#xff1a;这是一种基…...

设计模式-创建-单例模式

4.1.1 模式介绍 定义 单例模式&#xff08;Singleton Pattern&#xff09;是 Java 中最简单的设计模式之一&#xff0c;此模式保证某个类在运行期间&#xff0c;只有一个实例对外提供服务&#xff0c;而这个类被称为单例类。 作用 保证一个类只有一个实例为该实例提供一个全…...

使用mybatis-plus-generator配置一套适合你的CRUD

1、maven引入 mybatis-plus-generator 和模板引擎&#xff0c;你也可以使用freemarker之类的&#xff0c;看个人 <!-- 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去表达一个数据&#xff0c;因为只能放0和1&#xff0c;能表达的数据太少了&#xff0c;内存地址最小单位是字节 11111111 0x0011 1字节8bit,8bit才算作一个地址&#xff0c;地址是以字节为最小单位&#…...

当你的IDE装上GPT

文章目录前言下载安装使用步骤前言 我们可能要从“CV”工程师变成“KL工程师了&#xff0c;为什么叫”KL“工程师呢&#xff0c; 因为只要K和L两个指令就可以直接生成代码、修改代码&#xff0c;哪行代码不会点哪里&#xff0c;他都给你解释得明明白白。 提示&#xff1a;以下…...

一图看懂 pathlib 模块:面向对象的文件系统路径, 资料整理+笔记(大全)

本文由 大侠(AhcaoZhu)原创&#xff0c;转载请声明。 链接: https://blog.csdn.net/Ahcao2008 一图看懂 pathlib 模块&#xff1a;面向对象的文件系统路径, 资料整理笔记&#xff08;大全&#xff09;摘要模块图类关系图模块全展开【pathlib】统计常量intbooltuple模块9 fnmatc…...

前端如何将node.js 和mongodb部署到linux服务器上

本文首发自掘金。 记录了我第一次成功部署node.js 和mongodb到linux服务器上了&#xff0c;期间也遇到一些小坑&#xff0c;但是网上各位大佬记录的文章帮了大忙&#xff0c;所以我也将过程记录了下来。 安装Node 使用nvm linux上安装node&#xff0c;肯定首选nvm&#xff…...

mysql数据迁移

背景&#xff1a;随着时间的推移&#xff0c;交易系统中的订单表越来越大&#xff0c;目前达到500w数据。为了防止数据量过大导致的查询性能问题&#xff0c;现将订单表进行拆分&#xff0c;分为实时库和历史库。实时库保留近6个月的数据&#xff0c;用于退款业务需求&#xff…...

【4.3蓝桥备战】小朋友崇拜圈、正则问题

文章目录小朋友崇拜圈正则问题小朋友崇拜圈 小朋友崇拜圈 - 蓝桥云课 (lanqiao.cn) 拿到这道题要先把题目读懂。 下面的一行是表示&#xff1a;编号为i的小朋友&#xff0c;崇拜的对象为编号为path[i]的小朋友。 本题应该使用DFS&#xff0c;深度优先遍历找到可以成环的崇拜圈…...

MySQL读写分离中间件

1.什么是读写分离中间件&#xff1f; 就是实现当[写]的时候转发到主库&#xff0c;当[读]的时候转发到从库的工具。 很类似学习过的proxy,比如nginx proxy做动静分离. 2.为什么要实现读写分离&#xff1f; 1&#xff09;让主库专注于写&#xff0c;因为读可以有很多从库可以干…...

【Spring源码设计模式】单例模式外带设计模式的单例模式

Bean的概念 是Spring框架在运行时管理的对象&#xff0c;是任何引用程序的基本构建块。 Bean的属性 id属性&#xff1a;Bean的唯一标志名&#xff0c;必须以字母开头且不包含特殊字符 class属性&#xff1a;用来定义类的全限定名&#xff08;包名 类名&#xff09; name属性…...

go并发编程 —— singleflight设计模式

什么是singleflight singleflight是一种并发编程设计模式&#xff0c;将同一时刻的多个并发请求合并成一个请求&#xff0c;以减少对下游服务的压力 为什么叫singleflight fly可以理解为请求数&#xff0c;singleflight就是单个请求 使用场景 该模式主要用于防止缓存击穿 …...

【LeetCode】二叉树的中序遍历(递归,迭代,Morris遍历)

目录 题目要求&#xff1a;给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 方法一&#xff1a;递归 方法二&#xff1a;迭代 思路分析&#xff1a; 复杂度分析 代码展示&#xff1a; 方法三&#xff1a;Morris 遍历 思路分析&#xff1a; 复杂度分析…...

银行数字化转型导师坚鹏:数字化转型背景下的银行柜员提升之道

数字化转型背景下的银行柜员提升之道 课程背景&#xff1a; 很多银行都在开展银行数字化运营工作&#xff0c;目前存在以下问题急需解决&#xff1a; l 不清楚银行数字化运营包括哪些关键工作&#xff1f; l 不清楚银行数字化运营工作的核心方法论&#xff1f; l 不清楚银行数字…...

ChatGPT的平替来了?一文总结 ChatGPT 的开源平替,你值得拥有

文章目录【AIGC精选】总结 ChatGPT 的开源平替&#xff0c;你值得拥有1.斯坦福发布 Alpaca 7B&#xff0c;性能匹敌 GPT-3.52.弥补斯坦福 Alpaca 中文短板&#xff0c;中文大模型 BELLE 开源3.国产AI大模型 ChatGLM-6B 开启内测4.中文 Alpaca 模型 Luotuo 开源5. ChatGPT 最强竞…...

关于数据同步工具DataX部署

1.DataX简介 1.1 DataX概述 DataX 是阿里巴巴开源的一个异构数据源离线同步工具&#xff0c;致力于实现包括关系型数据库(MySQL、Oracle等)、HDFS、Hive、ODPS、HBase、FTP等各种异构数据源之间稳定高效的数据同步功能。 源码地址&#xff1a;GitHub - alibaba/DataX: DataX是…...

如何开发JetBrains插件

1 标题安装 IntelliJ IDEA 如果您还没有安装 IntelliJ IDEA&#xff0c;从官方网站下载并安装 IntelliJ IDEA Community Edition&#xff08;免费&#xff09;或 Ultimate Edition&#xff08;付费&#xff09;。 2 创建插件项目 在 IntelliJ IDEA 中&#xff0c;创建一个新…...

企业采购成本管理的难题及解决方案

企业采购成本控制是企业管理中的一个重要方面&#xff0c;也是一个不容易解决的难题。企业采购成本控制面临的难题包括以下几个方面&#xff1a; 1、采购流程复杂 企业采购通常需要经过一系列的流程&#xff0c;包括采购计划、采购申请、报价、比价、议标、合同签订、验收、付…...

龙蜥白皮书精选:基于 SM4 算法的文件加密(fscrypt)实践

文/张天佳 通常我们会以文件作为数据载体&#xff0c;使用磁盘&#xff0c;USB 闪存&#xff0c;SD 卡等存储介质进行数据存储&#xff0c;即便数据已经离线存储&#xff0c;仍然不能保证该存储介质不会丢失&#xff0c;如果丢失那么对于我们来说有可能是灾难性的事件。因此对…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式&#xff0c;然后找到相应的网卡&#xff08;可以查看自己本机的网络连接&#xff09; windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置&#xff0c;选择刚才配置的桥接模式 静态ip设置&#xff1a; 我用的ubuntu24桌…...

redis和redission的区别

Redis 和 Redisson 是两个密切相关但又本质不同的技术&#xff0c;它们扮演着完全不同的角色&#xff1a; Redis: 内存数据库/数据结构存储 本质&#xff1a; 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能&#xff1a; 提供丰…...

Python实现简单音频数据压缩与解压算法

Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中&#xff0c;压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言&#xff0c;提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...