Spring framework Day19:Spring AOP xml配置示例二

一、开始学习

1、新建项目,结构如下

2、添加 spring 依赖
 <!-- spring 的核心依赖 --><dependencies><!-- https://mvnrepository.com/artifact/org.springframework/spring-context --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.23</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.4.5</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.8</version></dependency></dependencies>

AspectJ 是 eclipse 开源组织编写的一套强大的 AOP 框架, 它拥有特殊的编译器和类加载器,因此可以在编译时创建 代理和类加载时创建代理,但由于 spring 本身对 AOP 的实现是基于运行时创建代理的,所以只能使用 jdk 和 cglib 来创建代理,但 spring 却使用了 AspectJ 的切入点表达式 以及相关的注解,使用起来更加的简单和方便 。

使用AspectJ,你可以通过定义切面来在不修改原始代码的情况下,将通用功能织入到应用程序中。

3、在 service 包下新建一个 UserService 类 
@Slf4j
public class UserService {public void add(){log.info("添加用户...");}}
4、在 aspect 包下新建一个 ServiceAspect 切面类
/*** @Date 2023-10-12* @Author qiu* 这是一个切面类*/
@Slf4j
public class ServiceAspect implements MethodBeforeAdvice, AfterReturningAdvice, MethodInterceptor, ThrowsAdvice {/*** 环绕通知** @param invocation 回调处理器,用于调用目标对象的方法* @return* @throws Throwable*/@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {log.info("环绕通知前...");// 调用目标对象方法Object proceed = invocation.proceed();log.info("环绕通知后....");return proceed;}/*** 后置通知** @param returnValue 目标方法的返回值* @param method      目标对象的方法* @param args        目标方法所需要的参数* @param target      目标对象* @throws Throwable*/@Overridepublic void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {log.info("后置通知...");}/*** 前置通知** @param method 准备调用的目标对象* @param args   目标方法的所需要的参数* @param target 目标对象(被代理的对象)* @throws Throwable 有可能抛出的异常*/@Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {log.info("前置通知...");}/*** 异常通知,根据官方文档说明* 该方法名必须叫做 afterThrowing* 并且必须包含一个 Exception 参数** @param e*/public void afterThrowing(Exception e) {log.info("异常通知...." + e.getMessage());}
}

这是一个使用AspectJ实现的切面类示例。该切面类实现了MethodBeforeAdviceAfterReturningAdviceMethodInterceptorThrowsAdvice这几个接口。

其中:

  1. invoke()方法是环绕通知,在目标方法执行前后进行拦截,并在前后打印日志。
  2. afterReturning()方法是后置通知,在目标方法正常返回后执行,并打印日志。
  3. before()方法是前置通知,在目标方法执行前执行,并打印日志。
  4. afterThrowing()方法是异常通知,在目标方法抛出异常时执行,并打印异常信息。

通过使用这些切面通知,你可以在应用程序中将这些关注点逻辑切入到目标方法的执行过程中,实现更灵活和可维护的代码结构。

5、在 resources 包下新建一个 beans.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.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 装配 UserService(目标对象)    --><bean id="userService" class="edu.nf.ch19.service.UserService"/><!-- 装切面,将切面纳入 spring 容器中管理    --><bean id="serviceAspect" class="edu.nf.ch19.aspect.ServiceAspect"/><!-- Aop 配置 proxy-target-class="true" 属性设置为 true表示强制使用 cglib 生成代理,无论目标对象有没有实现接口--><aop:config proxy-target-class="true"><!-- 配置切入点,spring 使用了 AspectJ 的切入点表达式来实现了 AOP 中切入点的概念,通过切入点表达式可以找到需要增强的目标方法。而找到的这些目标方法就称之为连接点。id 属性指定一个切入点的唯一标识,expression 用于声明切入点表达式。切入点表达式的语法:execution(访问修饰符 包名.类名.方法名(参数类型))也可以使用通配符来扩大切入点的范围execution(访问修饰符 包名.*.*(..))--><aop:pointcut id="myPointcut" expression="execution(* edu.nf.ch19.service.UserService.*(..))"/><!-- 配置通知器(也就是切面),使用 advice-ref 属性引用上面装配的切面pointcut-ref 引用切入点的 id--><aop:advisor advice-ref="serviceAspect" pointcut-ref="myPointcut"/></aop:config></beans>

 这是一个使用Spring AOP配置的XML示例。该配置文件定义了一个userService的目标对象和一个serviceAspect的切面对象,并通过AOP将切面应用到目标对象的方法上。

解析该配置文件的主要内容如下:

  1. 配置了userService的目标对象。通过指定class属性为edu.nf.ch19.service.UserService,将该类装配为 Spring 容器中的一个 bean。

  2. 配置了serviceAspect的切面对象。通过指定class属性为edu.nf.ch19.aspect.ServiceAspect,将该类装配为 Spring 容器中的一个 bean。

  3. <aop:config> 标签内配置了 AOP 相关的内容。通过设置proxy-target-class属性为true,启用了基于类的代理。

  4. 定义了 myPointcut 切点,使用表达式execution(* edu.nf.ch19.service.UserService.*(..))来匹配 edu.nf.ch19.service.UserService 类中的所有方法。

  5. 定义了 advisor,将serviceAspect作为通知(advice-ref)应用到 myPointcut 切点(pointcut-ref)。

通过这样的配置,你可以实现在edu.nf.ch19.service.UserService类的所有方法上应用serviceAspect切面对象中定义的通知逻辑。

6、测试
public class Main {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");UserService service = context.getBean(UserService.class);service.add();}}

运行结果

7、看图分析

1)什么是连接点?

目标对象的方法(被切入的方法)就称之为连接点,一个切入点可以对应目标对象的的多个连接点。AOP是对一个类的方法在不进行任何修改的前提下进行增强,那么UserService 里的 add()方法,就是连接点。

2)什么是通知?

通知(也叫增强)就是对目标行为植入额外的逻辑代码,从而增强原有的功能。切面类(通知类)里面的所有方法都是增强方法。

3)什么是切入点?

执行 add() 方法的时候本来是只有添加用户,但是执行后输出了环绕通知、前置通知、后置通知,也就是说,add()方法已经被增强了,被增强的方法就叫做切入点。

4)什么是切面?

切面是用于编写切面逻辑的一个类,这个类很类似于JDK动态代理中的回调处理器或者cglib中的方法拦截器,主要就是将需要增强目标对象的功能代码编写在这个类中,而这些功能增强的代码就是切面逻辑。 通知是增强的方法,会有多个,切入点是需要增强的方法,也会有多个,哪个切入点需要添加哪个通知,它们之间的关系就叫做切面。

5)什么是切面类(通知类)?

通知(增强)是一个方法,方法不能独立存在需要写在类中,这个类就叫切面类(通知类)。

 6)什么是代理?
AOP 是在不改变原有设计 ( 代码 ) 的前提下对其进行增强的,它的底层采用的是代理模式实现
的,所以要对原始对象进行增强,就需要对原始对象创建代理对象,在代理对象中的方法把通知
[ :UserService 中的 add 方法 ] 内容加进去,就实现了增强 , 这就是我们所说的代理 (Proxy)

 在运行时动态创建的对象,称之为代理对象,负责调用目标对象的方法,并执行增强功能。

 7)  什么是目标?

被代理的对象就是目标对象。

目标对象就是要被增强的类(UserService)。

8)什么是织入?

将切面中的增强逻辑应用到目标具体的连接点上并产生代理的过程称之为织入。

切面类中的增强方法应用到 UserService 的 add() 方法中的这个过程就是织入。

因此通常描述为“将通知织入到具体的目标”。

织入的时机可以分为以下几种:

  1. 类加载时织入,需要特殊的类加载器(LTW)

  2. 编译时织入,需要特殊的编译器(CTW)

  3. 运行时织入,通常使用JDK或者CGLIB在程序运行创建代理对象,

    spring就是基于运行时织入的。(注意:spring仅仅只是用到了AspectJ的切入点表达式和注解,但并没有使用AspectJ的类加载和编译时织入功能,而是使用JDK和CGLIB在运行时生成代理对象。)

 二、使用 AspectJ 的好处?

使用 AspectJ 有以下几个好处:

  1. 更强大的切面编程能力:AspectJ 提供了更丰富、更灵活的切面编程功能,可以针对更细粒度的 Join Point(连接点)进行切面编程。它支持更多的切点表达式,可以在方法的入参、返回值、异常等多个层面进行切面逻辑的定义,使得切面的编写更加灵活和精确。

  2. 更高效的性能:AspectJ 不依赖动态代理机制,使用字节码增强技术,生成修改后的目标类字节码,将切面逻辑直接插入到目标类的指定位置。这种静态织入方式比运行时的动态代理织入更高效,减少了额外的代理调用开销,提升了系统的运行性能。

  3. 更广泛的应用场景:AspectJ 可以与 Spring AOP 进行无缝集成,可以作为 Spring 框架的一部分使用。除了在 Spring 应用中使用外,AspectJ 还可以用于 JavaEE 应用、独立的 Java 应用,甚至能够修改第三方类库的字节码,具备更广泛的应用场景。

  4. 更丰富的功能扩展:AspectJ 提供了一些特殊的切面类型,例如 percflowpertarget 等,可以实现更复杂的切面逻辑。此外,AspectJ 还提供了一些高级功能,如异常处理、事务管理等,可以扩展切面的应用范围,使得切面编程更加强大和灵活。

总的来说,使用 AspectJ 可以提供更强大、更灵活的切面编程能力,同时具备更高的性能效率和更广泛的应用场景,是一个优秀的切面编程框架。

三、总结

本章节多了很多个理论知识点,连接点、通知、切入点、切面、代理、目标、织入,这本个理论很重要,也是 AOP 切面编程的最重要的知识,要想学好 AOP 就要理解它的思想,把这八个理解了就差不多了。

四、gitee 案例

案例完整地址:https://gitee.com/qiu-feng1/spring-framework.git

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

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

相关文章

将 vue2+ElementU 项目打包成安卓app

目标&#xff1a;将vue项目打包成安卓app 工具&#xff1a;HbuilderX 1.在HbuilderX中创建一个 5App 项目 创建好的app项目目录 2.将vue项目打包 2.1 在 vue.config.js 中添加公共路径&#xff08;解决打包后的app图片不显示问题&#xff09; module.exports defineConfig(…

软件测试(一)概念

软件测试 软件测试的生命周期&#xff1a; 需求分析→测试计划→ 测试设计、测试开发→ 测试执行→ 测试评估 需求分析&#xff1a;需求是非完整&#xff0c;需求是否正确测试计划&#xff1a;确定软件由谁测试&#xff0c;什么时候开始&#xff0c;什么时候结束&#xff0c;…

Java Kids-百倍提速【Mac IOS】

引言&#xff1a;当今社会&#xff0c;创新和提升效率已经成为了大家普遍的追求。无论是个人生活还是企业经营&#xff0c;我们都希望能够以更高的效率完成任务&#xff0c;节省时间和资源。因此&#xff0c;提速成为了一种时代的要求&#xff0c;而"Java Kids 百倍提速&q…

博客项目(前后端分离)(servlet实战演练)

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;实战项目 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01;! 文章目录 前言…

Vue 网络处理 - axios 异步请求的使用,请求响应拦截器

目录 一、axiox 1.1、axios 简介 1.2、axios 基本使用 1.2.1、下载核心 js 文件. 1.2.2、发送 GET 异步请求 1.2.3、发送 POST 异步请求 1.2.4、发送 GET、POST 请求最佳实践 1.3、请求响应拦截器 1.3.1、拦截器解释 1.3.2、请求拦截器的使用 1.3.3、响应拦截器的使用…

Umi3实战教程

一、框架介绍 umi是蚂蚁金服的前端开发框架&#xff0c;它内置了路由、web/移动端UI库、数据流、权限控制、常用hooks库、构建、部署、测试、等等一些工具&#xff0c;几乎涵盖了正常前端开发要用到的所有工具。 二、环境准备 pnpm 相比npm、yarn&#xff0c;pnpm更小更快扁平…

虚幻引擎:如何实现骨骼重定向

前言&#xff1a; 为什么需要做骨骼重定向&#xff0c;因为当前角色素材没有对应的动画&#xff0c;这时候我们可以找个身高体型差不多的带有动画素材的另一个角色来做重定向&#xff0c;这样我们就可以得到我们需要的动画素材了。 1.首先创建两个骨骼的IK绑定 2.然后给两个骨骼…

【算法|前缀和系列No.2】牛客网 DP35 【模板】二维前缀和

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【牛客网刷题】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希…

发面试题:(四)synchronized和lock区别

synchronized 关键字 synchronized关键字解决的是多个线程之间访问资源的同步性&#xff0c;synchronized关键字可以保证被它 修饰的方法或者代码块在任意时刻只能有一个线程执行。 另外&#xff0c;在 Java 早期版本中&#xff0c; synchronized属于重量级锁&#xff0c;效率…

vue3学习源码笔记(小白入门系列)------KeepAlive 原理

目录 说明组件是如何被缓存的&#xff0c;什么时候被激活对于KeepAlive 中组件 如何完成激活的对于KeepAlive 中组件 如何完成休眠的 总结 说明 Vue 内置了 KeepAlive 组件&#xff0c;实现缓存多个组件实例切换时&#xff0c;完成对卸载组件实例的缓存&#xff0c;从而使得组…

竞赛 深度学习+python+opencv实现动物识别 - 图像识别

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络3.1卷积层3.2 池化层3.3 激活函数&#xff1a;3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 inception_v3网络5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; *…

DHorse v1.4.2 发布,基于 k8s 的发布平台

版本说明 优化特性 在集群列表增加集群版本&#xff1b;修改Jvm的GC指标名&#xff1b; 解决问题 解决shell脚本换行符的问题&#xff1b;解决部署历史列表页&#xff0c;环境名展示错误的问题&#xff1b;解决指标收集功能的异常&#xff1b; 升级指南 升级指南 DHorse…

零宽空格引发的问题

有人跟我反馈说有bug。 我说&#xff1a;啥bug&#xff1f; 对方说&#xff1a;刚申请的内部用户的账号登录不上去。 我说&#xff1a;还有这种事&#xff0c;报啥错&#xff1f; 登录的时候报了这个错&#xff1a; 我一看还好还好&#xff0c;跟上一次不一样的错&#xff…

“探寻服务器的无限潜能:从创意项目到在线社区,你会做什么?”

文章目录 每日一句正能量前言什么是服务器&#xff1f;服务器能做什么&#xff1f;服务器怎么用&#xff1f;部署创意项目&#xff0c;还是在线社区亦或做其他的&#xff1f;后记 每日一句正能量 未知的下一秒&#xff0c;千万不要轻言放弃。 前言 在数字化时代&#xff0c;服…

SpringBoot面试题7:SpringBoot支持什么前端模板?

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:SpringBoot支持什么前端模板? Spring Boot支持多种前端模板,其中包括以下几种常用的: Thymeleaf:Thymeleaf是一种服务器端Java模板引擎,能够…

基于马尔可夫随机场的图像去噪算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1、马尔可夫随机场的基本原理 4.2、基于马尔可夫随机场的图像去噪算法 5.算法完整程序工程 1.算法运行效果图预览 原图&#xff1a; 加入噪声的图像&#xff1a; 滤波后的图像 迭代过程…

2-k8s-控制器介绍

文章目录 一、控制器类型二、Deployment控制器三、SatefulSet控制器四、Daemonset控制器五、Job控制器六、CronJob 控制器 一、控制器类型 Deployment&#xff1a;适合无状态的服务部署StatefullSet&#xff1a;适合有状态的服务部署DaemonSet&#xff1a;一次部署&#xff0c…

关于ts的keyof

type props_type {name: string,age: number }const props: props_type {name: tjq,age: 18 }for (const key in props) { //props[key]出现红色波浪线const value props[key]; }why&#xff1f; 经过我查阅多方资料&#xff0c;在网上看到一个比较合适的例子 地址&#xf…

OpenRemote: Java 开源 IoT 物联网开发平台,匹配智慧城市、智能家居、能源管理

OpenRemote 是一个直观、用户友好的基于Java语言的开源 IoT 物联网设备管理平台&#xff0c;它包括从连接设备到构建应用程序和特定领域的智能应用程序的所有功能和特性。通过OpenRemote物联网平台&#xff0c;用户可以收集和处理来自不同设备的传感器数据&#xff0c;适用于智…

Gson反序列化原理

前言 序列化和反序列化是日常工作中经常使用的工具&#xff0c;一般用于对象的持久化保存或者对象的网络传输&#xff0c;一般有两种情况&#xff0c;一种是对象本身实现了Serializable接口&#xff0c;这种情况下可以利用jdk自带的功能或者Kryo等这种封装好的序列化反序列化工…