深入理解 Spring AOP:面向切面编程的原理与应用

news2024/11/23 21:38:25

一、概述

AOPAspect Orient Programming)是一种设计思想,是软件设计领域中的面向切面编程,它是面向对象编程(OOP)的一种补充和完善。它以通过预编译方式和运行期动态代理方式,实现在不修改源代码的情况下给程序动态统一添加额外功能的一种技术。

(一)AOP与OOP之间的区别

OOP:将面向对象理解为一个静态过程(例如一个系统有多少个模块,一个模块有哪些对象,对象有哪些属性)

AOP:面向切面的运行期代理方式,理解为一个动态过程,可以在对象运行时动态织入一些扩展功能或控制对象执行。

(二)AOP的运用场景

实际项目中通常会将系统分为两大部分,一部分是核心业务,一部分是非核业务。在编程实现时我们首先要完成的是核心业务的实现,非核心业务一般是通过特定方式切入到系统中,这种特定方式一般就是借助AOP进行实现。

(三)AOP原理与术语

Aop运行原理:

Aop术语:

切面(Aspect):一个使用@Aspect注解描述的类的对象。@

通知(Advice):在切面上某一特定的连接点上要执行的使用特定通知注解描述的方法。一般用于提供非核心事务。

连接点(JoinPoint):程序执行过程中某个特定的运行节点。程序运行到该节点前后会执行通知方法。

切入点(PointCut):对多个连接点的一种定义,一般可以理解为多个连接点的集合。

连接点与切入点:

连接点可以理解为被代理类的每个被拦截的方法。

切入点可以理解被拦截的类。使用@Pointcut注解通过切入点表达式定义。

二、开发步骤

(一)原理:

通过@Aspect注解标识AOP中的切面类型,基于切面类型构建的对象用于为目标对象进行功能扩展或控制目标对象的执行。

通过@Pointcut注解描述切面中的一个特定方法结合实参(切入点表达式)来定义切入点(连接点集合)。该特定方法无实际意义,但不可或缺,其主要作用是承载@Pointcut注解。​​​​​​​

通过5种通知注解描述切面方法,这些方法用于进行功能扩展或控制目标对象的招待。

其中@Around描述的方法最为特殊,方法用于控制目标方法的执行。即,目标方法的执行是从@Around描述的方法开始,并从@Around描述的方法结束。在@Around方法执行过程中会调用其它4种通知注解描述的通知方法。

该注解描述的方法需要ProceedingJoinPoint类型的形参。该类型定义了一个连接点。该类型的对象用于封装要执行的目标方法相关的信息。该类型的对象只能作为@Around注解描述的方法的形参。

其余4种通知方法通常用于扩展功能。

此4种通知所描述的方法只能使用JoinPoin类型形参来定义目标方法。

特别注意

JoinPoin的包为:org.aspectj.lang.JoinPoint;千万不能引错包。

当JoinPoin引成:org.aopalliance.intercept.Joinpoint;时

(二)所需依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

(三)开发步骤

(四)五种通知方法的执行流程

三、开发增强

(一)通知增强

1.作用:通知注解主要用于描述控制目标方法执行或对目标方法进行扩展的方法。

2.通知分类:

在基于Spring Aop编程的过程中,基于AspectJ框架标准,Spring中定义了五种类型的通知:

@Around:访问目标类或方法之前进入该注解描述的方法。

@Before:如果存在该注解描述的方法,则在@Around描述的方法中,调用(ProceedJoinPoint)jp.proceed()方法(即目标方法)之前调用该注解描述的方法。

@AfterReturning:如果存在该注解描述的方法,则在jp.proceed()方法成功执行之后立即执行该注解描述的方法。

@AfterThrowing:如果存在该注解描述的方法,则在jp.proceed()方法异常之后立即执行该注解描述的方法。

@AfterThrowing注解常用属性:

value属性:用于指定切入点表达式或切入点表达式的引用。

throwing属性:指定要处理的异常。该属性的属性值必须与描述方法的异常参数名相同。如果不同则会抛出异常如下图所示:

@After:如果存在该注解描述的方法,@AfterReturning|@AfterThrowing描述的方法执行之后执行该注解描述的方法。

当@After注解描述的方法执行之后,程序会将控制权交还于@Around描述的方法,继续执行@Around描述的方法后续语句。

使用说明:

在切面类中使用什么通知,由业务决定,并不需要把所有通知都写入切面类。

3.通知注解使用方式:

方式一:可以通过切入点表达式作为实参直接传递给通知注解的方式使用。

应用场景:一个切面类中需要处理的连接点的通知方法较少时可以使用该方式。

特点:使用该方式时,省略由此类连接点组成的切入点的定义。

方式二:可以通过将切入点表达式的引用作用实参传递给注解的方式使用。

应用场景:一个切面类中需要处理的连接点的通知方法较多。

特点:

使用该方式时,需要使用@Pointcut注解定义此类连接点构成的切入点。该注解的实参则为切入点表达式。

而切入点表达式的引用即为:@Pointcut注解描述的方法。

(二)切入点表达式增强

1.作用:用于指定要扩展功能的类或方法。

2.分类:

bean表达式:用于匹配指定bean对象的所有方法。​​​​​​​

within表达式:用于匹配包下所有类内的所有方法。​​​​​​​

excution表达式:用于按指定语法规则匹配到具体方法。​​​​​​​

@annotation表达式:用于匹配指定注解描述的方法。

3.使用位置:

位置一:切入点表达式做为实参赋值于@Pointcut注解的value属性。

示例:@Pointcut("bean(goodsSvsImpl)")

位置二:切入点表达式做为实参赋值给通知注解。

示例:@Around("bean(goodsSvsImpl)")

4.bean表达式(重点):

应用场景:

bean表达式一般应用于类级别,实现粗粒度的切入点表达式的定义。

使用方式:

方式一:通过具体bean对象定义切入点。

示例:bean("userServiceImpl")。

特点:此时的切入点则由该对象的所有方法对应的连接点组成。

方式二:通过通配符*带指定后缀的bean对象定义切入点。

示例:bean("*ServiceImpl")。

特点:此时的切入点则由带后缀的所有bean对象中的所有方法对应的连接点组成。

使用说明:

如果通过具体bean对象指定切入点表达式时,则该bean对象是由Spring容器管理的一个bean对象,表达式内部的名字应该是Spring容器中某个bean的name。(Spring管理的bean对象的命名规则:在默认情况下,Spring管理的bean对象名字是其类名首字母小写)。

5.within表达式(了解):

应用场景:

within表达式应用于包、类级别,实现粗粒度的切入点表达式的定义。

使用方式:

within("aop.service.UserSvsImpl"):指定包中具体类的所有方法对应的连接点构成的切入点。

within("aop.service.*"):指定当前包下的所有类的所有方法对应的连接点构成的切入点。

within("aop.service..*"):指定当前包及其子包中所有类的所有方法对应的连接点构成的切入点。

使用说明:

如果within应用于类级别时,此时,表达式中的类名必须是类名,不是Spring管理的该类的对象的名字。

适用场景:

对所有业务bean都要进行功能增强,但是bean名字没有规则。

按业务模块(不同包下的业务)对bean对象进行业务功能增强。

6.execution表达式(重点):

应用场景:

execute表达式应用于方法级别,实现细粒度的切入点定义。

语法:

execute(returnType packageName.className.methodName([paramList]))。

示例:

execution(void aop.service.UserServiceImpl.addUser())匹配addUser方法。

execution(void aop.service.PersonServiceImpl.addUser(String)) 方法参数必须为String的addUser方法。

execution(* aop.service..*.*(..)) 万能配置。

7. @annotation表达式(重点):

应用场景:

@annotation表达式应用于方法级别,实现细粒度的切入点表达式定义。

开发步骤:

第一步:定义自定义注解。

第二步:使用自定义注解描述要拦截的目标方法。

第三步:使用@annotation(自定义注解)定义切入点表达式,并使用该切面表达式赋值给通知注解和定义扩展功能的方法。

(三)切面优先级设置实现

(四)Spring AOP关键对象与术语总结

四、SpringAOP数据库事务管理

(一)SpringAOP数据库事务管理方式

1.声明式数据库事务管理原理

默认情况下,如果被注解的数据库操作方法中发生了unchecked异常,所有的数据库操作将rollback;如果发生了checked异常,则该数据库操作还是会提交commit。​​​​​​​

checked异常:通常是Exception类的子类(非RuntimeException类)

表示无效,不是程序中可以预测的。比如无效的用户输入,文件不存在,网络或数据库链接错误等不由程序内部控件产生的异常。

此类异常必须在代码中显式处理。使用try-catch或throw方式。

定义此类异常必须继承Exception类。

unchecked异常:通常是RuntimeException类的子类。

表示程序逻辑错误。

不需要在代码中显式地捕获处理此类异常。

2.Spring声明式数据库事务管理方法:

通过start transaction|begin显示开启事务​​​​​​​

通过commit|rollback结束事务。​​​​​​​

MySql数据库默认开启数据库事务,通过手动提交或执行回滚来结束事务。

3.Spring事务管理特点

Spring的事务管理是线程安全的。​​​​​​​

事务方法的嵌套调用会产生事务传播。​​​​​​​

父类声明的@Transaction会对子类的所有方法进行事务增强。子类覆盖重写父类方式可覆盖其@Transaction中的声明配置。​​​​​​​

当@Transaction描述类时,类中的方法可以通过属性配置来覆盖类上的@Transaction配置。(类上配置全局是可读写,可在某个方法上改为只读)

(二)@Transaction实现声明式数据库事务管理

1.@Transaction注解属性

属性说明:

2.使用规则

描述对象:接口、接口方法和实现类、接口实现方法。

Spring团队建议:该注解应用于描述实现类或实现类的方法。在接口上使用时,只能当设置了基于接口的代理时,该注解才生效。

方法的访问权限:该注解只能描述public修饰的方法。​​​​​​​

@Transaction的事务开启是基于接口的或者是基于类的代理对象被创建。因此在同一个类中的一个方法调用另一个带事务的方法时,将不会开启事务。​​​​​​​

多线程下事务管理因为线程不属于Spring托管,故线程不能够默认使用Spring事务,也不能获取Spring注入的Bean。​​​​​​​

在被Spring声明式事务管理的方法内开启多线程,多线程内的方法不被事务控制。​​​​​​​

一个使用了@Transaction的方法,如果方法内包含多线程的使用,方法内部出现异常,不会回滚线程中调用方法的事务。

3.@Transaction 注解的实质

该注解使用JDBC的事务方式进行事务管理。并通过动态代理机制实现。

(三)Spring事务特性

1.实现事务的隔离级别

通过@Transaction的isolation属性指定。​​​​​​​

实现示例:

2.实现事务传播行为:

通过@Transaction的propagation属性指定。​​​​​​​

实现方式:

​​​​​​​

事务嵌套:

(四)Spring事务回滚规则

(五)多线程事务管理

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ML 系列:机器学习和深度学习的深层次总结( 19)— PMF、PDF、平均值、方差、标准差

一、说明 在概率和统计学中&#xff0c;了解结果是如何量化的至关重要。概率质量函数 &#xff08;PMF&#xff09; 和概率密度函数 &#xff08;PDF&#xff09; 是实现此目的的基本工具&#xff0c;每个函数都提供不同类型的数据&#xff1a;离散和连续数据。 二、PMF 的定义…

基于STM32的八位数码管显示Proteus仿真设计

基于STM32的八位数码管显示Proteus仿真设计 1.主要功能2.仿真设计3. 程序设计4. 设计报告5. 资料清单&下载链接 基于STM32的八位数码管显示Proteus仿真设计(仿真程序设计报告讲解视频&#xff09; 仿真图proteus 8.9 程序编译器&#xff1a;keil 5 编程语言&#xff1a;…

Linux grep命令详解(多图、多示例)

文章目录 grep基本说明grep参数简单示例列举参数-v(反选)-r -l -H -i(目录子目录、只打印匹配文件、输出文件名、忽略大小写)-c -n -o(匹配次数、输出行号、只打印匹配)-A -B -C(前后行) 正则表达式基本正则表达式与扩展正则表达式 grep示例附录:正则表达式基本字符特殊字符Per…

力扣:225 用队列实现栈

栈、队列 栈&#xff1a; 弹夹&#xff0c;后进先出 队列&#xff1a; 排队&#xff0c;先进先出 描述&#xff1a; var MyStack function () {// 定义两个数组&#xff0c;模拟队列this.queue []this._queue [] };/** * param {number} x* return {void}*/ MyStack.protot…

【MFC编程(一)】MFC概述

文章目录 MFC概述MFC组成MFC对比Windows APIMFC类库基类CObject命令发送类CCmdTarget应用程序结构类应用程序线程支持类CWinThread/CWinApp文档类CDocument文档模板类CDocTemplate 窗口类窗口基类CWnd边框窗口类CFrameWnd视图类CView MFC概述 MFC&#xff08;Microsoft Founda…

【客观理性深入讨论国产中间件及数据库-科创基础软件】

随着国产化的进程&#xff0c;越来越多的国企央企开始要求软件产品匹配过程化的要求&#xff0c; 最近有一家银行保险的科技公司对行为验证码产品就要求匹配国产中间件&#xff0c; 于是开始了解国产中间件都有哪些厂家 一&#xff1a;国产中间件主要产品及厂商 1 东方通&…

基于Python的校园爱心帮扶管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

pycharm小游戏贪吃蛇及pygame模块学习()

由于代码量大&#xff0c;会逐渐发布 一.pycharm学习 在PyCharm中使用Pygame插入音乐和图片时&#xff0c;有以下这些注意事项&#xff1a; 插入音乐&#xff1a; - 文件格式支持&#xff1a;Pygame常用的音乐格式如MP3、OGG等&#xff0c;但MP3可能需额外安装库&#xf…

A018基于Spring Boot的民宿租赁系统

&#x1f64a;作者简介&#xff1a;在校研究生&#xff0c;拥有计算机专业的研究生开发团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339; 赠送计算机毕业设计600…

​基于学习的地铁客流动态预测智能调度方法

1 文章信息 文章题为“A Learning Based Intelligent Train RegulationMethod With Dynamic Prediction forthe Metro Passenger Flow”&#xff0c;该文于2023年发表至“IEEE TRANSACTIONS ON INTELLIGENT TRANSPORTATION SYSTEMS”。文章的核心观点是提出了一种基于学习的智…

SpringBoot+FileBeat+ELK8.x版本收集日志

一、准备环境 1、ElasticSearch&#xff1a;8.1.0 2、FileBeat&#xff1a;8.1.0 3、Kibana&#xff1a;8.1.0 4、logstach&#xff1a;8.1.0 本次统一版本&#xff1a;8.1.0,4个组件&#xff0c;划分目录&#xff0c;保持版本一致。 说明&#xff1a;elasticsearch和kib…

【大数据学习 | HBASE】habse的表结构

在使用的时候hbase就是一个普通的表&#xff0c;但是hbase是一个列式存储的表结构&#xff0c;与我们常用的mysql等关系型数据库的存储方式不同&#xff0c;mysql中的所有列的数据是按照行级别进行存储的&#xff0c;查询数据要整个一行查询出来&#xff0c;不想要的字段也需要…

论文速读:动态再训练-更新用于无源目标检测的Mean Teacher(ECCV2024)

原文标题&#xff1a;Dynamic Retraining-Updating Mean Teacher for Source-Free Object Detection 中文标题&#xff1a;动态再训练-更新用于无源目标检测的Mean Teacher 本篇文章为论文速读&#xff0c;以帮助大家快速了解大意&#xff0c;具体详解可以看这篇分享。ECCV2024…

科研绘图系列:R语言带有面积区域的折线图(linechart)

文章目录 介绍加载R包数据画图准备图1图2图3图4图5图6图7图8图9图10合并所有图形系统信息介绍 带有面积区域的折线图通常被称为面积图(Area Chart)。面积图结合了折线图和条形图的特点,通过在折线下方的区域填充颜色或纹理,来展示一个或多个组的数值如何随第二个变量(通常…

Golang--文件操作

1、文件 文件&#xff1a;文件用于保存数据&#xff0c;是数据源的一种 os包下的File结构体封装了对文件的操作&#xff08;记得包os包&#xff09; 2、File结构体--打开文件和关闭文件 2.1 打开文件 打开文件&#xff0c;用于读取&#xff08;函数&#xff09;&#xff1a; 传…

Ubuntu学习笔记 - Day3

文章目录 学习目标&#xff1a;学习内容&#xff1a;学习笔记&#xff1a;vim简介vim键盘图工作模式 vim移动光标操作上下左右移动翻页 vim替换和删除操作替换删除 vim插入模式详解进入模式搜索 vim底行模式操作保存退出行号 学习目标&#xff1a; 一周掌握 Linux基本使用技巧 …

Java中的JDBC的详解

数据库驱动包 Java提出的一套关于数据库操作的接口 各个数据库厂商要把自己的api对接到/适配到jdbc上 程序员只需要掌握一套api就可以操作不同的数据库了 数据库厂商提供的这个原生api适配到jdbc转换程序&#xff0c;称为“数据库驱动包” 1&#xff09;创建数据源 //1,创…

Apache-Hive数据库使用学习

前期准备 Hadoop-分布式部署&#xff08;服务全部在线&#xff09; Mysql-node1节点部署&#xff08;确认安装正常&#xff09; apache-hive -node1节点部署&#xff08;需要与MySQL元数据联动存储&#xff09; 参考博客&#xff1a; Hadoop Hadoop集群搭建-完全分布式_hadoop完…

【极客兔兔-Web框架Gee详解】Day2 上下文Context

文章目录 一、框架结构二、设计上下文(Context):day2-context/gee/context.go1. 设计Context必要性1.1 接口粒度过细:1.2 缺乏扩展性:2. 代码3. 优势三、路由(Router): day2-context/gee/router.go四、框架入口:day2-context/gee/gee.go1. 代码五、框架使用: day2-context/m…

LeetCode17. 电话号码的字母组合(2024秋季每日一题 59)

给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 示例 1&#xff1a; 输入&#xff1a;digits “23” 输出&#xff1a;[“…