Spring-aop特点,专业术语及案例演示

一.aop简介

AOP(Aspect-Oriented Programming)是Spring框架的一个重要特性,它通过将横切关注点(cross-cutting concerns)从核心业务逻辑中分离出来,以模块化的方式在整个应用程序中重复使用。以下是关于AOP的简介及其特点:

简介:

  • AOP是一种编程范式,它通过将横切关注点切割出来,将其模块化,并将其应用于多个类和模块,以提高代码的重用性和可维护性。
  • 横切关注点是指与核心业务逻辑无关但存在于多个类或模块中的非功能性需求,例如日志记录、性能监控、事务管理等。

特点:

  1. 模块化:AOP允许将横切关注点从核心业务逻辑中提取出来,形成独立的切面(Aspect),使得关注点的逻辑可以独立于各个模块。
  2. 解耦:AOP通过解耦横切关注点与核心业务逻辑,使得它们可以独立演化和变化,提高了模块之间的松耦合程度。
  3. 重用性:AOP允许将切面应用于多个类和模块,从而实现了关注点的重用,避免了代码的重复编写。
  4. 可维护性:将横切关注点抽象为切面后,使得代码结构更清晰,易于理解和维护。
  5. 动态性:AOP可以在运行时动态地将切面应用到目标对象上,而不需要修改目标对象的源代码,增强了系统的灵活性和可扩展性。
  6. 多样性:Spring框架支持不同类型的切面编程,包括基于代理的AOP和基于字节码增强的AOP。这样可以选择最适合应用程序需求的AOP实现方式。

在Spring框架中,AOP的实现采用了代理模式和动态代理技术。Spring提供了多种AOP的实现方式,包括基于XML配置的AOP、基于注解的AOP和基于纯Java配置的AOP(JavaConfig)等,开发者可以根据具体需求选择适合的方式来配置和使用AOP。

 二.aop中的专业术语

  1. 切面(Aspect):切面是一个模块化单元,用于解耦和封装横切关注点的逻辑。切面由切点和通知组成,它定义了何时在何处应用通知。

  2. 切点(Pointcut):切点定义了在应用程序中哪些位置应该应用通知。它通过表达式或模式匹配规则来指定需要被拦截的连接点(Join Point)。

  3. 连接点(Join Point):连接点是在应用程序执行过程中可以插入切面的特定点。例如方法执行、异常抛出、字段访问等都可以是连接点。

  4. 通知(Advice):通知是在切面的特定连接点上执行的动作。在Spring AOP中,有以下几种通知类型:

    • 前置通知(Before Advice):在连接点之前执行的通知。
    • 后置通知(After Advice):在连接点之后执行的通知。
    • 返回通知(After Returning Advice):在连接点成功完成后执行的通知。
    • 异常通知(After Throwing Advice):在连接点发生异常时执行的通知。
    • 环绕通知(Around Advice):在连接点前后都执行的通知,可以控制方法的执行。
  5. 引入(Introduction):引入是一种给现有类添加新方法或属性的方式。它允许在不修改原始类代码的情况下,向类添加新功能。

  6. 织入(Weaving):织入是将切面应用到目标对象上以创建新的代理对象的过程。在Spring AOP中,织入可以在编译时、类加载时或运行时进行。

  7. 目标对象(Target Object):目标对象是被切面通知的真实对象。它是应用程序中具体业务逻辑的实现。

  8. 异常处理(Exception Handling):异常处理是在连接点发生异常时,切面执行的特定动作。它可以捕获和处理异常,提供错误处理或回滚事务等功能。

三.案例演示 

1.前置通知

1.1 先准备接口

package com.YU.aop.biz;public interface IBookBiz {// 购书public boolean buy(String userName, String bookName, Double price);// 发表书评public void comment(String userName, String comments);
}

1.2然后再准备好实现类

package com.YU.aop.biz.impl;import com.YU.aop.biz.IBookBiz;
import com.YU.aop.exception.PriceException;public class BookBizImpl implements IBookBiz {public BookBizImpl() {super();}public boolean buy(String userName, String bookName, Double price) {// 通过控制台的输出方式模拟购书if (null == price || price <= 0) {throw new PriceException("book price exception");}System.out.println(userName + " buy " + bookName + ", spend " + price);return true;}public void comment(String userName, String comments) {// 通过控制台的输出方式模拟发表书评System.out.println(userName + " say:" + comments);}}

1.3对我们的目标对象进行JavaBean配置 

<!--目标对象--><bean class="com.YU.aop.biz.impl.BookBizImpl" id="bookBiz"></bean>

1.4 编写前置系统日志通知

package com.YU.aop.advice;import java.lang.reflect.Method;
import java.util.Arrays;import org.springframework.aop.MethodBeforeAdvice;/*** 买书、评论前加系统日志* @author YU**/
public class MyMethodBeforeAdvice implements MethodBeforeAdvice {@Overridepublic void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
//		在这里,可以获取到目标类的全路径及方法及方法参数,然后就可以将他们写到日志表里去String target = arg2.getClass().getName();String methodName = arg0.getName();String args = Arrays.toString(arg1);System.out.println("【前置通知:系统日志】:"+target+"."+methodName+"("+args+")被调用了");}}

1.5配置系统通知XML中的JavaBean

<!--通知--><bean class="com.YU.aop.advice.MyMethodBeforeAdvice" id="myMethodBeforeAdvice"></bean>

1.6 配置代理XML中的JavaBean

<!-- 代理--><bean class="org.springframework.aop.framework.ProxyFactoryBean" id="bookProxy"><!-- 配置目标对象 --><property name="target" ref="bookBiz"></property><!-- 配置代理接口,目标对象的接口 --><property name="proxyInterfaces"><value>com.YU.aop.biz.IBookBiz</value></property><property name="interceptorNames"><list><value>myMethodBeforeAdvice</value></list></property></bean>

1.7 测试代码开始测试

package com.YU.aop.test;import com.YU.aop.biz.IBookBiz;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @author YU* @create 2023-08-17 15:14*/
public class Test1 {public static void main(String[] args) {//建模ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
//        IBookBiz bookBiz = (IBookBiz) context.getBean("bookBiz");IBookBiz bookBiz = (IBookBiz) context.getBean("bookProxy");bookBiz.buy("死仔","我的26岁女房客",18.8d);bookBiz.comment("死仔","真好看");}
}

测试结果:

 由测试结果可得知,不仅获取到了我们的参数,同时根据方法获取到了我们的系统日志,也就是前置通知

2. 后置通知

2.1 先准备好后置通知的系统日志

package com.zking.aop.advice;import java.lang.reflect.Method;
import java.util.Arrays;import org.springframework.aop.AfterReturningAdvice;/*** 买书返利* @author Administrator**/
public class MyAfterReturningAdvice implements AfterReturningAdvice {@Overridepublic void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {String target = arg3.getClass().getName();String methodName = arg1.getName();String args = Arrays.toString(arg2);System.out.println("【后置通知:买书返利】:"+target+"."+methodName+"("+args+")被调用了,"+"该方法被调用后的返回值为:"+arg0);}}

2.2 配置后置系统通知的XML的JavaBean

<!--后置通知--><bean class="com.YU.aop.advice.MyAfterReturningAdvice" id="myAfterReturningAdvice"></bean>

并在前面已经配置好的代理接口中添加一个value值

 2.3 测试结果

 由测试结果我们可以得知,后置通知永远都在方法执行后才会显示通知,与前置通知不同的是每次前面的方法调用后都会返回一个参数

3.环绕通知

3.1 环绕通知就是前置通知和后置通知的结合,在实际应用开发中,我们一般不会单独编写前置通知和后置通知,单独使用前置通知或者后置通知时,我们会使用环绕通知,将里面前置(后置)通知的功能注释,以达到单独使用的目的

3.2 环绕通知的系统日志

package com.YU.aop.advice;import java.util.Arrays;import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;/*** 环绕通知* 	包含了前置和后置通知* * @author Administrator**/
public class MyMethodInterceptor implements MethodInterceptor {@Overridepublic Object invoke(MethodInvocation arg0) throws Throwable {String target = arg0.getThis().getClass().getName();String methodName = arg0.getMethod().getName();String args = Arrays.toString(arg0.getArguments());System.out.println("【环绕通知调用前:】:"+target+"."+methodName+"("+args+")被调用了");
//		arg0.proceed()就是目标对象的方法Object proceed = arg0.proceed();System.out.println("【环绕通知调用后:】:该方法被调用后的返回值为:"+proceed);return proceed;}}

3.3 配置环绕通知的XML的JavaBean与前置通知和后置通知一致

3.4 测试结果

 

由测试结果得知,环绕通知就是前置通知和后置通知的结合,优点就是不需要再多次去进行配置及编码,所以就像我们前面所说在实际开发应用中我们一般都会选择使用环绕通知

4.异常通知

4.1 异常通知的系统日志和其他系统日志不同的是,方法名为固定的afterThrowing,不能修改

package com.YU.aop.advice;import org.springframework.aop.ThrowsAdvice;import com.YU.aop.exception.PriceException;/*** 出现异常执行系统提示,然后进行处理。价格异常为例* @author Administrator**/
public class MyThrowsAdvice implements ThrowsAdvice {public void afterThrowing(PriceException ex) {System.out.println("【异常通知】:当价格发生异常,那么执行此处代码块!!!");}
}

4.2 在我们正常程序出问题没有去配置异常通知时会出现报错,并且不会执行后面的后置通知,如以下情况

4.3 异常处理配置和前面的配置相同

4.4 当我们配置好异常通知模块时,程序出现异常时会上报日志进行提示

5.过滤通知

5.1 直接在XML中配置JavaBean

<!--过滤通知--><bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" id="regexpMethodPointcutAdvisor"><property name="advice" ref="myAfterReturningAdvice"></property><property name="pattern" value=".*buy"></property></bean>

 

将图中指出部分替换成过滤通知

 测试结果:

对比框中内容,在调用过buy方法后进行过滤,第二次调用时不再buy方法而是comment方法 

四.总结

aop是面向切面编程,普通程序由上而下正常执行,aop的程序执行是先执行到目标对象的目标方法中,如果连接点上由前置通知,则先执行前置通知再执行目标方法,最后如果目标方法有后置通知则最后执行后置通知代码,不管是前置通知,后置通知,环绕通知,异常通知,过滤通知,代码都是非业务核心代码,如日志、事务的管理(开启、提交、回滚)         

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS自己实现一个步骤条

前言 步骤条是一种用于引导用户按照特定流程完成任务的导航条&#xff0c;在各种分步表单交互场景中广泛应用。例如&#xff1a;在HIS系统-门诊医生站中的接诊场景中&#xff0c;我们就可以使用步骤条来实现。她的执行步骤分别是&#xff1a;门诊病历>遗嘱录入>完成接诊…

【数据结构】堆

文章目录 优先级队列几点说明小根堆大根堆 建堆算法向下调整算法 & 初始化堆代码&#xff1a;向上调整算法 & 插入删除代码&#xff1a; 时间复杂度手稿&#xff1a; 优先级队列 在优先级队列中存储的元素具有优先级&#xff0c;可以返回优先级较高的元素。 逻辑结构采…

记录一下基于jeecg-boot3.0的待办消息移植记录

因为之前没有记录&#xff0c;所以还要看代码进行寻找&#xff0c;比较费劲&#xff0c;所以今天记录一下&#xff1a; 1、后端 SysAnnouncementController 下面函数增加待办的几个显示内容给前端用 具体代码如下&#xff1a; /*** 功能&#xff1a;补充用户数据&#xff0c…

低成本无刷高速吹风机单片机方案

高速吹风机的转速一般是普通吹风机的5倍左右。一般来说&#xff0c;吹风机的电机转速一般为2-3万转/分钟&#xff0c;而高速吹风机的电机转速一般为10万转/分钟左右。高转速增加了高风速。一般来说&#xff0c;吹风机的风力只有12-17米/秒&#xff0c;而高速吹风机的风力可以达…

Nginx的安装及负载均衡搭建

一.Nginx的安装 1&#xff09;准备安装环境 yum install -y make gcc gcc-c pcre-devel pcre zlib zlib-devel openssl openssl-develPERE PCRE(Perl Compatible Regular Expressions)是一个Perl库&#xff0c;包括 perl 兼容的正则表达式库。 nginx的http模块使用pcre来解…

CTFshow 限时活动 红包挑战7、红包挑战8

CTFshow红包挑战7 写不出来一点&#xff0c;还是等了官方wp之后才复现。 直接给了源码 <?php highlight_file(__FILE__); error_reporting(2);extract($_GET); ini_set($name,$value);system("ls ".filter($_GET[1])."" );function filter($cmd){$cmd…

彻底卸载Android Studio

永恒的爱是永远恪守最初的诺言。 在安装Android Studio会有很多问题导致无法正常运行&#xff0c;多次下载AS多次错误后了解到&#xff0c;删除以下四个文件才能彻底卸载Android Studio。 第一个文件&#xff1a;.gradle 路径&#xff1a;C:\Users\yao&#xff08;这里yao是本…

双向-->带头-->循环链表

目录 一、双向带头循环链表概述 1.什么是双向带头循环链表 2.双向带头循环链表的优势 3.双向带头循环链表简图 二、双向带头循环链表的增删查改图解及代码实现 1.双向带头循环链表的头插 2.双向带头循环链表的尾插 3.双向带头循环链表的头删 4.双向带头循环链表的尾删…

Swift 基础

工程目录 请点击下面工程名称&#xff0c;跳转到代码的仓库页面&#xff0c;将工程 下载下来 Demo Code 里有详细的注释 点击下载代码&#xff1a;swift-01

PHP 使用ThinkPHP实现电子邮件发送示例

文章目录 首先我们需要设置我们的邮箱客户端授权&#xff0c;获取到授权码找到我们的邮箱设置去账号中找到这一堆服务&#xff0c;找到后开启smtp服务开启服务后管理服务 接下来需要去下载相应的第三方类库(我这里使用的是PHPMailer)在thinkPHP中封装一下邮件服务类实际调用效果…

Web和云开发,Rust会起飞?

Web和云开发&#xff0c;Rust会起飞&#xff1f; 一、前言 二、大厂偏爱&#xff0c;Rust的未来 三、Rust做Web的雄心 四、有必要换Rust做Web&#xff1f; 1.效率和性能 2.可靠性和可维护性 五、Rust先苦后甜 六、用Rust前的几个问题 七、开发界的强者 一、前言 去年…

小研究 - 主动式微服务细粒度弹性缩放算法研究(二)

微服务架构已成为云数据中心的基本服务架构。但目前关于微服务系统弹性缩放的研究大多是基于服务或实例级别的水平缩放&#xff0c;忽略了能够充分利用单台服务器资源的细粒度垂直缩放&#xff0c;从而导致资源浪费。为此&#xff0c;本文设计了主动式微服务细粒度弹性缩放算法…

工博士与纷享销客达成战略合作,开启人工智能领域合作新篇章

近日&#xff0c;工博士与纷享销客在上海正式签署了战略合作协议&#xff0c;正式拉开了双方在人工智能与数字营销领域的合作序幕。这次合作将为双方带来更多机遇和发展空间&#xff0c;并为全球人工智能领域的客户提供更高效、智能的CRM解决方案。 < 双方项目人员合影 >…

【分布式共识算法】Basic Paxos 算法

basic paxos算法&#xff1a;描述的是多个节点就某个值达成共识。 muti-paxos 算法&#xff1a;描述的是执行多个basic paxos实例&#xff0c;就一系列值达成共识。 共识其实&#xff0c;比如当多个客户端请求服务器&#xff0c;修改同一个值X 多个阶段达成共识。 原理 角色…

07_Hudi案例实战、Flink CDC 实时数据采集、Presto、FineBI 报表可视化等

7.第七章 Hudi案例实战 7.1 案例架构 7.2 业务数据 7.2.1 客户信息表 7.2.2 客户意向表 7.2.3 客户线索表 7.2.4 线索申诉表 7.2.5 客户访问咨询记录表 7.3 Flink CDC 实时数据采集 7.3.1 开启MySQL binlog 7.3.2 环境准备 7.3.3 实时采集数据 7.3.3.1 客户信息表 7.3.3.2 客户…

【CTF-web】备份是个好习惯(查找备份文件、双写绕过、md5加密绕过)

题目链接&#xff1a;https://ctf.bugku.com/challenges/detail/id/83.html 经过扫描可以找到index.php.bak备份文件&#xff0c;下载下来后打开发现是index.php的原代码&#xff0c;如下图所示。 由代码可知我们要绕过md5加密&#xff0c;两数如果满足科学计数法的形式的话&a…

图片懒加载指令-vueUse

基于Vue的自定义钩子集合 https://vueuse.org/ 适用于Vue 3和Vue2.7版本之后 基于vueUse定义懒加载指令

ByteBuffer 使用

ByteBuffer 使用 1 java.nio包中的类定义的缓冲区类型2 缓冲区常用属性2.1缓冲区的容量(capacity)2.2 缓冲区的位置(position)2.3 缓冲区的限制(limit)2.4 缓冲区的标记(mark)2.5 剩余容量 remaining/hasRemaining 3 缓冲区常用方法3.1 创建缓冲区3.1.1 allocate方法3.1.2 wrap…

NLP语言模型概览

语言模型结构分类 Encoder-Decoder&#xff08;Transformer&#xff09;: Encoder 部分是 Masked Multi-Head Self-Attention&#xff0c;Decoder 部分是 Casual Multi-Head Cross-Attention 和 Casual Multi-Head Self-Attention 兼具。比如T5&#xff0c;BART&#xff0c;MA…

美能达打印机刷卡扫描文件后,用户收不到扫描邮件

环境: 柯尼卡美能达一体机 bizhub 287 域服务器 Windows server 2019 问题描述: 新员工在域服务器创建账户后同步到打印服务器上面,他们在打印机扫描文件后,自动发邮件那个邮箱上没有他们邮件,导致他们也收不到邮件 正常是用户在打印机上刷卡后扫描件文件为PDF格式,…