你看这个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一样, 也会通过责任链来执行所有的方法增强。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/6178.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据结构——红黑树

目录 概念 性质 结点的定义 插入 调整 当p是g的左孩子时 当p为g的右孩子时 插入完整代码 红黑树的检测 红黑树完整代码&#xff08;包括测试数据&#xff09; 概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&…

如何有效备考PMP?

随着PMP证书含金量直线上升&#xff01;现在PMP证书就跟黄金一样&#xff0c;即保值又升值。 今天小编应势出一篇关于如何高效备考PMP的方法&#xff0c;在备考生快过来看看吧&#xff01; 1、准备好所需要的教材&#xff0c;视频&#xff0c;试题内容 备考备考&#xff0c;你…

蓝桥杯刷题冲刺 | 倒计时5天

作者&#xff1a;指针不指南吗 专栏&#xff1a;蓝桥杯倒计时冲刺 &#x1f43e;马上就要蓝桥杯了&#xff0c;最后的这几天尤为重要&#xff0c;不可懈怠哦&#x1f43e; 文章目录1.方格迷宫2.字符串删减1.方格迷宫 题目 链接&#xff1a; 4943. 方格迷宫 - AcWing题库 给定一…

Sam Altman专访:GPT-4没太让我惊讶,ChatGPT则让我喜出望外

导读ChatGPT、GPT-4 无疑是 2023 年年初人工智能界最大的「爆款」。3 月 26 日&#xff0c;OpenAI CEO、ChatGPT 之父 Sam Altman 接受了著名学者与科技播客、麻省理工大学研究员 Lex Fridman 的专访&#xff0c;Sam 分享了从OpenAI内部视角如何看待ChatGPT和GPT-4的里程碑式意…

分享:数据库存储与索引技术(三)LSM树实现案例

欢迎访问 OceanBase 官网获取更多信息&#xff1a;https://www.oceanbase.com/ 本文来自OceanBase社区分享&#xff0c;仅限交流探讨。原作者马伟&#xff0c;长期从事互联网广告检索系统的研发&#xff0c;对数据库&#xff0c;编译器等领域也有浓厚兴趣。 文章目录1. MemTab…

2.2.2 第2遍:程序细节

这段话主要解释了C程序中#include指令和头文件的作用。头文件包含了编译器所需的信息&#xff0c;例如函数名、常量、以及如何使用它们等。在C程序中&#xff0c;头文件通常用于包含库函数&#xff0c;例如stdio.h文件中包含了输入和输出函数&#xff08;如printf()&#xff09…

LCHub:ChatGPT4和低代码来临,程序员面临下岗?

一个网友吐槽道: “ 建站出来了,你们说程序员会失业。 低代码出来了,你们说程序员会失业。 Copilot出来了,你们说程序员会失业。 Chatgpt出来了,你们说程序员会失业 虽然这只是网友的吐槽,但却引起了小编的好奇。为何程序员那么容易被新技术取代?今天小编打算跟大家…

Waline在Butterfly主题中的应用

LeanCloud 设置 (数据库) 国内版的LeanCloud需要绑定域名&#xff0c;所以我们直接选择国外版的LeanCloud 登陆注册 注册&#xff1a;点击这里进行跳转注册成功后进入控制台&#xff0c;选择 创建应用 。 创建完成后进入应用&#xff0c;下拉找到 设置 , 会有 AppID 、AppK…

ASO优化之应用商店关键词的实现

投放正确的合适的关键词&#xff0c;能够确保我们的应用获得更高的相关性和知名度。如果我们已经完成研究并想要竞争目标关键词&#xff0c;就需要在商品详情中去实施投放它们。 要在 Google Play Store 中投放——我们要打开 Google Play 控制台并点击“主要应用详情”选项卡…

基于模型预测控制(MPC)的微电网调度优化的研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

VMware创建和使用虚拟网络

文章目录如何打开虚拟网络编辑器让虚拟机使用有线、无线网卡1. 点击“添加网络”2. 虚拟机使用电脑自带无线网卡3. 虚拟机使用电脑自带有线网卡重置虚拟网络在使用虚拟机的过程中&#xff0c;有时会需要让虚拟机使用物理机的网络设备直接与外部连接&#xff0c;例如让虚拟机通过…

Win11启用IE方法

呉師傅 Win11是微软目前的最新系统&#xff0c;尽管该系统非常不错&#xff0c;但是还是有很多不一样的地方&#xff0c;有的用户发现Win11没有了IE浏览器&#xff0c;那么Win11没有IE浏览器怎么办呢&#xff0c;有的旧网页需要IE浏览器才能进入&#xff0c;下面就给大家提供一…

怎么把两个音频合成一个

在创作音乐、制作视频等领域&#xff0c;经常需要将音频文件进行合并处理&#xff0c;但对于没有专业工具和知识的朋友来说&#xff0c;音频合并可能是一项复杂的任务。本篇文章就要为大家介绍合并音频的方法&#xff0c;让大家能够快速地将音频文件合并成需要的部分&#xff0…

leaflet: 地图上叠加日夜区域(126)

第126个 点击查看专栏目录 本示例的目的是介绍如何在vue+leaflet中显示日夜交替叠加区域。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共68行)安装插件相关API参考:专栏目标示例效果 配置方式 1)查看基础设…

ChatGPT能胜任高级程序员吗?

与开发人员信任的其他软件开发工具不同&#xff0c;AI工具在训练、构建、托管和使用方式等方面都存在一些独特的风险。 自2022年底ChatGPT发布以来&#xff0c;互联网上便充斥着对其几乎相同比例的支持和怀疑的论调。不管你是否喜欢它&#xff0c;AI正在逐步进入你的开发组织。…

【设计模式】Bridge Design pattern 桥接模式

1.桥接模式要解决的问题 多个维度的变化引起的继承组合指数级增长 例子 一个物体有不同形状和不同颜色&#xff0c;如何用类来表示它们&#xff0c;这里包含了两个变化维度&#xff0c;一个是物体的形状&#xff0c;一个是颜色 继承的方式 如果使用继承的方式&#xff0c;此…

抖音seo优化系统常见的交付形式|技术开发

1. 一次性交付&#xff1a;将整个SEO优化系统一次性交付给客户&#xff0c;包括相关的文档、工具和数据分析报告&#xff0c;由客户自行操作和维护。 2. 阶段性交付&#xff1a;将SEO优化系统分为不同的阶段进行交付&#xff0c;每个阶段完成后进行检查和评估&#xff0c;根据…

2. [手把手教你搭建] 之 在linux上搭建mysql

1. 首先下载mysql安装包&#xff0c;这里一般有如下2种下载方式 wgt方式下载&#xff1a;进入服务器中的package目录&#xff08;注&#xff1a;该目录是我自己创建的&#xff0c;用于存放所有应用的安装包&#xff0c;您也可以随便创建其他名称的目录来存放安装包&#xff09…

k8s部署

kubernetes简要 Kubernetes 是用于自动部署, 扩展和管理容器化应用程序的开源系统. 它将组成应用程序的容器组合成逻辑单元, 以便于管理和服务发现 kubernetes功能简介 服务发现和负载均衡 存储编排 自动部署和回滚 自动完成装箱计算 自我修复 密钥与配置管理 Kuberne…

算法题记录

力扣的算法题&#xff1a;1154 给你一个字符串 date &#xff0c;按 YYYY-MM-DD 格式表示一个 现行公元纪年法 日期。返回该日期是当年的第几天。 示例 1&#xff1a; 输入&#xff1a;date “2019-01-09” 输出&#xff1a;9 解释&#xff1a;给定日期是2019年的第九天。 示例…