【Spring】面向切面编程详解(AOP)

article/2025/8/18 21:02:07

文章目录

    • 一、AOP概述
        • 什么是AOP
        • AOP应用场景
    • 二、AOP的基本术语
        • 术语介绍
        • 术语举例详解
    • 三、AOP实例说明
    • 四、通知类型详解
        • 概述
        • 前置通知
        • 后置通知
        • 环绕通知
        • 最终通知
    • 六、AOP实现声明式事务
    • 结语

🌕博客x主页:己不由心王道长🌕!
🌎文章说明:spring🌎
✅系列专栏:spring
🌴本篇内容:对面向切面编程即AOP进行一个详细讲解(对所需知识点进行选择阅读呀~)🌴
☕️每日一语:在人生的道路上,即使一切都失去了,只要一息尚存,你就没有丝毫理由绝望。因为失去的一切,又可能在新的层次上复得。☕️
🕤作者详情:作者是一名双非大三在校生,喜欢Java,欢迎大家探讨学习,喜欢的话请给博主一个三连鼓励。🕤

一、AOP概述

什么是AOP

AOP(Aspect Oriented Program)即面向切面编程。我们先回顾以下三层架构,三层架构式垂直架构,即一层对另一层提供服务,不能越级访问,分级进行运作。
在这里插入图片描述
上述架构是垂直分布的,而面向切面则是一个切面:
到底是什么切面呢?
就是把各种类中冗余的代码提取出来,在需要用的时候就横向切入,就像一个切面一样。
到底是什么冗余代码呢?事务处理、异常处理等等!突然来一大堆听不懂。
举个栗子:
在这里插入图片描述

比如说事务控制,在我们的业务中,虽然查询是最多的,但是添加、修改、删除也不少。查询不用提交事务,而后面的都得提交事务,在JDBC中,我们一般都手动提交事务。
在这里插入图片描述
都得提交事务,难道要在调用每一个方法执行完之后都编写一段提交事务的代码吗?这当然可以,不过太傻了!

④解决办法
上面看到了事务提交每次都编写代码会造成代码冗余,复用性不好,也不利于维护(事务提交与代码耦合死了)。
这是我们可以把上面重复的代码提取出来,制成一个切面,需要用的地方就声明它

⑤ 实现先行剧透:通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。

AOP应用场景

日志记录、性能统计、安全控制、事务处理、异常处理

二、AOP的基本术语

术语介绍

Joint point(连接点): 连接点就是可以被拦截的点,在程序中,通常指的是方法,在Spring中只支持方法类型的连接点。在其他的地方可能支持类,这里记住方法就行了。
Pointcut(切点): 切入点就是对连接点中哪些点进行拦截的定义,对连接点(一般所有方法都可做连接点)进行条件筛选。
Advice(通知/增强): 通知就是我们拦截到切点之后,对它做的事情叫做通知或者增强,比如上面的事务,我们拦截到addUser之后,要对它增强,使其在完成方法之后增强提交事务,异常的时候发生回滚。
Aspect(切面): 即切入点和通知的结合(多个切入点共有一个通知,连在一起像不像一个面?)
Weaving(织入): 指的是在把增强的方法加入到目标对象(切点方法的拥有者)来创建新的对象的过程,spring采用的是动态代理织入(jdk动态代理和子类动态代理都有),AspectJ采用编译期织入和类装载织入。

术语举例详解

先说一个故事吧:
有一天,小吉和他的小伙伴(连接点)去后山的山洞冒险,发现山洞里有一个shiti,小吉和其他一部分小伙伴(切点)就把这个shiti抬了出去,回家后其他抬了的小伙伴都die了,这时候小吉的身上开始发绿,爷爷看到就说:“不好,是绿shi寒警告”。

Joint point(连接点): 在上面的故事里,小吉和他的伙伴都能够被绿,就是都能被增强,可以看到绿shi寒警告是可以作用在上面所以人的身上。在Spring中,这些人就等于可以被增强的方法。
Pointcut(切点): 在上面的故事里,只有小吉和其他几名抬了这个东西的小伙伴收到了绿shi寒,其他没有抬的小伙伴则没有事。可以看出来Pointcut(切点)是有条件的Joint point(连接点),抬了的人被增强了。
Advice(通知/增强): 上面的小伙伴在抬了以后,那个东西就对他们进行了增强。
Aspect(切面): 切点和通知的结合,上面的切点就是抬了的小伙伴和小吉,通知是抬之后的作用,切点有很多,连载一起就像一个面一样。

三、AOP实例说明

一、创建maven工程
二、导入相关配置文件

<dependencies><!-- https://mvnrepository.com/artifact/org.springframework/spring-context --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.5.RELEASE</version></dependency><!-- https://mvnrepository.com/artifact/org.springframework/spring-core --><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>5.2.5.RELEASE</version></dependency><!-- https://mvnrepository.com/artifact/org.springframework/spring-aop --><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>5.2.5.RELEASE</version></dependency><!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.6</version><scope>runtime</scope></dependency>

三、添加applicationContext.xml核心配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

注意、上面给了Aop的命名空间。

四、定义接口和实现类
这里的实现类里面定义的方法就是连接点,至于要增强哪个方法,由程序员根据自己的业务要求,自己指定,要增强的方法就是切点
在这里插入图片描述

package com.bipt.ServiceAop;/*** @author 不止于梦想* @date 2022/10/17 13:08*/
public interface UserService {public void save();public void addUser();
}package com.bipt.ServiceAop.impl;import com.bipt.ServiceAop.UserService;/*** @author 不止于梦想* @date 2022/10/17 13:09*/
public class ImplUserService implements UserService {@Overridepublic void save() {System.out.println("save......");}@Overridepublic void addUser() {System.out.println("AddUser.......");}
}

在Spring配置文件中添加bean,把ImplUserService作为连接点
在这里插入图片描述

四、写通知类和在配置文件中引入

package com.bipt.ServiceAop;/*** 定义通知类* @author 不止于梦想* @date 2022/10/17 13:14*/
public class MyAdvice {public void advice1(){System.out.println("吉尼抬没?");}
}

在这里插入图片描述

五、定义切入点和制作切面

<aop:config><!--配置切点,即在哪些方法用到增强,后面是表达式--><aop:pointcut id="mypointCut" expression="execution( void com.bipt.ServiceAop.impl.ImplUserService.save())"/><!--配置切面,切面就是通知加上增强--><aop:aspect id="myadvice" ref="Advice"><!--before表示前置通知,在切点执行之前执行,method则是通知里的一种方法--><aop:before method="advice1" pointcut-ref="mypointCut"></aop:before></aop:aspect></aop:config>

六、测试
测试要先导入测试的依赖,这里不用Spring的依赖,用junit。

 <!-- https://mvnrepository.com/artifact/junit/junit --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope>

然后编写测试类

package com.bipt;import com.bipt.ServiceAop.UserService;
import com.bipt.ServiceAop.impl.ImplUserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import javax.annotation.processing.SupportedAnnotationTypes;/*** @author 不止于梦想* @date 2022/10/17 13:47*/
public class MyTest {@Testpublic void AopTest(){ApplicationContext App = new ClassPathXmlApplicationContext("applicationContext.xml");UserService userService = (UserService) App.getBean("JointPoint");userService.save();}
}

测试结果如下:
在这里插入图片描述
可以看到结果正确,我们完成了一个入门测试,至于为什么通知在切入点之前执行是因为我们在上面配置切面的时候使用的是before,即前置增强。

四、通知类型详解

概述

通知类型大致分为六类: 分别是前置通知、后置通知、环绕通知、最终通知、异常抛出通知和引介通知。
上述通知中的引介通知我们是用不到的,这里不做介绍。

前置通知

即before,在上面的例子中我们可以清楚的看到,前置通知在切入点方法执行之前执行了。这就是前置通知的作用范围。前置通知的方式一把也可以用作权限验证。

后置通知

即after—running 在目标方法执行之后执行

<aop:pointcut id="after" expression="execution(* com.bipt.ServiceAop.impl.ImplUserService.save())"/><!--配置切面,切面就是通知加上增强--><aop:aspect  ref="Advice"><!--before表示后置通知,在切点执行之前执行,method则是通知里的一种方法-->
<!--            <aop:around method="advice2" pointcut-ref="mypointCut2" ></aop:around>--><!--后置通知--><aop:after-returning method="after_running" pointcut-ref="after" />

在这里插入图片描述

环绕通知

环绕通知是重点,是最重要的一个通知。环绕通知功能比较强大,它可以追加功能到方法执行的前后,这也是比较常用的方式,它可以实现其他四种通知类型的功能。
环绕通知的怎么做到在方法执行前后追加功能呢? 不难,做一个演示
在这里插入图片描述

最终通知

即after。不管前面发生什么,最终通知都会执行。这里进行演示

<aop:aspect id="myadvice" ref="Advice"><!--before表示后置通知,在切点执行之前执行,method则是通知里的一种方法--><aop:after method="advice1" pointcut-ref="mypointCut"></aop:after></aop:aspect>

结果:
在这里插入图片描述
可以看到两个方法执行循序与前置通知相反了。

六、AOP实现声明式事务

二、添加事务管理

事务分为声明式事务和编程式事务,编程式事务就是JDBC的事务提交、回滚等等,这样不太方便,我们有很多的方法都要用到事务,不能需要一个就编写一个,这样太重复了。我们可以把事务抽取出来,利用Spring提高的声明式事务管理来处理。
Spring声明式事务是基于AOP(面向切面)实现的
① 配置事务管理器
事务管理器有很多种,不同的数据访问层框架有不同的实现,而Mybatis的事务管理器为:DataSourceTransactionManager
在这里插入图片描述
②配置事务增强/通知(Advice)
在这里插入图片描述
③ 配置切面
在这里插入图片描述

配置代码:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/aop expression="com.bipt.controller"/></context:component-scan><!--导入配置文件--><context:property-placeholder location=" classpath:config.properties"></context:property-placeholder><!--配置数据源--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driver}"></bean><!--配置事务管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!--配置事务增强--><tx:advice id="transactionAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="login*"  read-only="true"/><tx:method name="register*" propagation="REQUIRED" rollback-for="Exception,RuntimeException" read-only="false"/></tx:attributes></tx:advice><!--配置切面--><aop:config><aop:advisor advice-ref="transactionAdvice" pointcut-ref="transactionPointcut"></aop:advisor><aop:aspect ref="dataSource"><aop:pointcut id="transactionPointcut" expression="execution(* com.bipt.service.*.*(..)) "/></aop:aspect></aop:config>
</beans>

结语

码字不易、觉得有帮助的小伙伴动动小手给个三连,无比感谢。


http://chatgpt.dhexx.cn/article/CFL7wE8D.shtml

相关文章

时间序列预测方法

之前一直在看时间序列预测方法的文献&#xff0c;最近终于有点头绪了&#xff0c;然后就花了些时间来做一下整理。时间序列预测方法可分为传统的&#xff0c;基于机器学习的和基于深度学习的&#xff0c;以下每一方面都列举了几个比较经典的模型算法。 目录 1 背景 2 传统的时…

时间序列预处理

数据预处理的主要流程为&#xff1a;数据清洗、特征选择、归一化处理、划分窗口、Shuffle和划分数据集等五个阶段。选用何种方法没有统一的标准&#xff0c;只能根据不同类型的分析数据和业务需求&#xff0c;在对数据特性做了充分的理解之后&#xff0c;再选择与其最适配的数据…

时间序列分析相关概念

1. 在时间序列分析中&#xff0c; 数学模型是什么&#xff1f;数学公式又是什么&#xff1f;数学推导过程又是什么&#xff1f;… … 一句话&#xff1a;用数学公式后者符号来表示现实存在的意义。数学是“万金油”的科学&#xff0c;它是作为工作和分析方法运用到某个学科当中…

时间序列预测方法总结

前言 对时间序列数据预测模型做个简单的分类&#xff0c;方便日后对其进一步研究&#xff0c;理清楚技术更新发展方向。 时间序列预测分析就是利用过去一段时间内某事件时间的特征来预测未来一段时间内该事件的特征。 预测场景 单步预测 单步单变量预测 &#xff1a;在时间序…

时间序列的聚类方法

时间序列的聚类方法 时间序列是按照时间排序的一组随机变量&#xff0c;它通常是在相等间隔的时间段内&#xff0c;依照给定的采样率&#xff0c;对某种潜在过程进行观测的结果。 时间序列数据是实值型的序列数据&#xff0c;具有数据量大、数据维度高以及数据是不断更新的等…

【时间序列预测】Autoformer 长时间序列预测

论文链接&#xff1a;http://xxx.itp.ac.cn/pdf/2106.13008.pdf Abstract 延长预测时间是极端天气预警和长期能源消耗规划等实际应用的关键需求。本文研究时间序列的长期预测问题。先前的基于 Transformer 的模型采用各种 self-attention 机制来发现长期依赖关系。然而&…

时间序列分析预测

全栈工程师开发手册 &#xff08;作者&#xff1a;栾鹏&#xff09; python数据挖掘系列教程 时间序列中常用预测技术&#xff0c;一个时间序列是一组对于某一变量连续时间点或连续时段上的观测值。参考&#xff1a;https://blog.csdn.net/u010414589/article/details/49622625…

时间序列预测

问题简介 简单来说&#xff0c;时间序列是按照时间顺序&#xff0c;按照一定的时间间隔取得的一系列观测值&#xff0c;比如我们上边提到的国内生产总值&#xff0c;消费者物价指数&#xff0c;利率&#xff0c;汇率&#xff0c;股票价格等等。时间间隔可以是日&#xff0c;周…

时间序列分析

http://blog.csdn.net/pipisorry/article/details/62053938 时间序列简介 时间序列是时间间隔不变的情况下收集的时间点集合。这些集合被分析用来了解长期发展趋势&#xff0c;为了预测未来或者表现分析的其他形式。但是什么时间序列&#xff1f;与常见的回归问题的不同&…

时间序列模型调查

RNN 模型 Recurrent Neural Network (回流神经网络,有的译做递归神经网络) 时间序列模型最常用最强大的的工具就是递归神经网络(recurrent neural network, RNN)。相比与普通神经网络的各计算结果之间相互独立的特点,RNN的每一次隐含层的计算结果都与当前输入以及上一次的…

时间序列模型

1. 时间序列分析方法概述 一个时间序列往往是一下几类变化形式的叠加或耦合。 &#xff08;1&#xff09;长期趋势变动&#xff1a;反映主要变化趋势&#xff1b; &#xff08;2&#xff09;季节变动 &#xff08;3&#xff09;循环变动 &#xff08;4&#xff09;不规则变动 使…

python创建时间序列_python 时间序列

将dataframe的列转化为时间序列 #https://www.cnblogs.com/bolgbjg/p/14013300.html #datetime.now()获取现在的时间&#xff0c;now.year,获取现在的年份&#xff0c;其他以此类推 #timedelta()表示两个datetime之间的时间差,默认单位是天 strftime()参数&#xff0c; strftim…

时间序列(数据分析)

目录 第11章 时间序列 11.1 日期和时间数据的类型及工具 11.1.1 字符串与datetime互相转换 11.2 时间序列基础 11.2.1 索引、选择、子集 11.2.2 含有重复索引的时间序列 11.3 日期范围、频率和移位 11.3.1 生成日期范围 11.3.2 频率和日期偏置 11.3.3 移位&#xff0…

时间序列介绍

什么是时间序列&#xff1f; 时间序列是按照一定时间顺序&#xff0c;按照一定的时间间隔取得的一系列观测值。 怎样做时间序列分析&#xff1f; 时间序列分析尝试找出序列值在过去所呈现的特征模式&#xff0c;假定这种模式在未来能够持续&#xff0c;进而对未来进行预测 时…

时间序列

时间序列 一、时间序列是什么&#xff1f;二、时间序列分类1.白噪声序列2.平稳非白噪声序列3.非平稳序列 三. 时间序列主要模型1. ARIMA如何挑选模型参数&#xff1a;Example and application: 总结 一、时间序列是什么&#xff1f; 时间序列是指某种现象某一指标在不同时间上…

经典时间序列的学习(一)简单的认识时间序列

1. 什么是时间序列 同一统计指标数值按照时间先后顺序排列而成的数据。本质上是反映一个变量随时间序列变化的趋势。 简单的例子就像是学生每一年的身高数据&#xff0c;这个也是一个时间序列。变量是我们的身高;每一年都不一样。我们支付宝或者微信的零钱&#xff0c;每一天…

【时间序列】时间序列基本概念总结

最近一直在接触时间序列&#xff0c;所以打算写一些有关时间序列的文章&#xff0c;预测部分会从规则开始、到传统模型、到机器学习、再到深度学习&#xff0c;此外也会介绍一些时间序列的基本概念&#xff0c;包括自相关、平稳性、滞后性、季节性等。 1.基本概念 1.1 时间序列…

备战数学建模35-时间序列预测模型

目录 一、时间序列概念与分解模型 1-时间序列数据与基本概念 2-时间序列分解 二、SPSS中七种指数平滑模型 1-七种指数平滑模型简介 2-七种指数平滑模型具体分析 三、ARIMA模型相关的知识点 四、时间序列模型经典案例 1-时间序列建模思路介绍 2-案例1销售数据预测 3-…

【时间序列】最完整的时间序列分析和预测(含实例及代码)

时间序列 在生产和科学研究中&#xff0c;对某一个或者一组变量 进行观察测量&#xff0c;将在一系列时刻所得到的离散数字组成的序列集合&#xff0c;称之为时间序列。 pandas生成时间序列过滤数据重采样插值滑窗数据平稳性与差分法 pandas生成时间序列 时间戳&#xff08;ti…

UCF 2021 Qualifying - H . Time to Eat + UCF HSPT 2020 - E . Use Giant Fans to Deal With Hurricanes?

题目&#xff1a; H . Time to Eat [ 问题 8933 ] [ 讨论 ] Description The UCF Programming Team has made it to the World Contest Finals (WF), thanks to the great team members and coaches. Fortunately for Dr. Orooji (Team Faculty Advisor), WF is in a city wit…