Spring framework Day20:Spring AOP xml配置示例三

前言

本章节我们继续学习 AspectJ!

AspectJ是一个基于Java语言的面向切面编程(AOP)的扩展框架,它的诞生解决了很多传统面向对象编程的问题。在传统的面向对象编程中,开发者通常会将一些通用功能或者横切关注点(cross-cutting concern)手动地嵌入到业务逻辑中,导致代码难以维护和理解。而AspectJ的出现则让开发者可以通过一种简单而优雅的方式来解决这些问题,使得应用程序的代码变得更加清晰、易于维护。

在本文中,我们将介绍AspectJ的基本概念、语法和使用方法。首先,我们将简要介绍AOP的概念,并与传统的面向对象编程作对比,以突出AspectJ的优越性。其次,我们将详细阐述AspectJ的语法和组成部分,包括切入点、通知和切面等。最后,我们将提供一些实际的示例来帮助读者更好地理解如何使用AspectJ来解决常见的应用程序开发问题。

相信通过本文的介绍,读者将会深入理解AspectJ的强大之处,掌握如何使用这个框架来构建高效、易于维护的应用程序。

一、开始学习

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>
3、在 service 包下新建一个类 UserService 类
@Slf4j
public class UserService {/*** 目标方法,也就是需要被增强的方法* 因此它就是一个连接点* @param name*/public String add(String name){log.info("添加用户..." + name);return "success";}}
4、在 aspect 包下新建一个 ServiceAspect 切面类

@Slf4j
public class ServiceAspect {/*** 自定义前置通知,可以给一个参数* 这个参数为连接点(JoinPoint)* 通过这个连接点可以拦截目标方法的参数等信息** @param jp*/public void before(JoinPoint jp) {log.info("执行前置通知,拦截的目标方法参数:" + jp.getArgs()[0]);}/*** 后置通知** @param jp        连接点* @param returnVal 目标的方法的返回值*/public void afterReturning(JoinPoint jp, Object returnVal) {log.info("后置通知,目标方法返回值:" + returnVal);}/*** 环绕通知** @param jp 连接点,继承 JoinPoint 接口* @return*/public Object around(ProceedingJoinPoint jp) throws Throwable {log.info("环绕通知前,目标方法参数:" + jp.getArgs()[0]);// 调用目标方法对象的方法Object returnVal = jp.proceed();log.info("环绕通知后,目标方法返回值:" + returnVal);return returnVal;}/*** 异常通知,当目标对象产生异常时会执行* 后置通知将不会再生效** @param jp 连接点* @param e  目标方法产生的异常对象*/public void afterThrowing(JoinPoint jp, Exception e) {log.info("异常通知,异常信息:" + e.getMessage());}/*** 最终通知,不管有没有异常产生最终通知都会被执行* @param jp 连接点*/public void after(JoinPoint jp){log.info("最终通知");}}

这个示例中的ServiceAspect类是一个使用AspectJ编写的切面类,其中包含了几个不同类型的通知方法。

  1. before(JoinPoint jp) 方法是一个前置通知。在目标方法执行之前被拦截执行。它接收一个JoinPoint对象作为参数,可以通过该对象获取目标方法的参数信息。在这个示例中,我们使用log.info方法记录了拦截的目标方法参数。

  2. afterReturning(JoinPoint jp, Object returnVal) 方法是一个后置通知。在目标方法成功返回之后被拦截执行。它接收一个JoinPoint对象和目标方法的返回值作为参数。在这个示例中,我们使用log.info方法记录了目标方法的返回值。

  3. around(ProceedingJoinPoint jp) 方法是一个环绕通知。它可以在目标方法执行的前后进行处理。在这个示例中,我们首先通过log.info方法记录了目标方法的参数信息,然后调用jp.proceed()方法来执行目标方法,最后再通过log.info方法记录了目标方法的返回值。注意,在环绕通知中必须显式地调用jp.proceed()方法来触发目标方法的执行。

  4. afterThrowing(JoinPoint jp, Exception e) 方法是一个异常通知。当目标方法抛出异常时被拦截执行。它接收一个JoinPoint对象和抛出的异常对象作为参数。在这个示例中,我们使用log.info方法记录了异常信息。

  5. after(JoinPoint jp) 方法是一个最终通知。无论目标方法是否成功执行,最终总会被执行。在这个示例中,我们使用log.info方法输出了一条简单的日志。

通过编写这些通知方法,我们可以根据不同的需求,在目标方法的不同执行阶段进行拦截和处理。例如,可以在前置通知中进行参数验证,后置通知中记录返回值,异常通知中处理异常情况等。AspectJ提供了灵活的语法和丰富的可操作性,使得开发人员可以轻松地实现横切关注点的处理。

 5、在 rsources 下新建一个 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"><!-- 装配目标对象 --><bean id="userService" class="edu.nf.ch20.service.UserService"/><!-- 装配切面 --><bean id="serviceAspect" class="edu.nf.ch20.aspect.ServiceAspect"/><!-- 配置 AOP --><aop:config><!-- 配置切入点 --><aop:pointcut id="myPointcut" expression="execution(* edu.nf.ch20.service.UserService.*(..))"/><!-- 配置切面,ref 引用切面的 bean 的 id --><aop:aspect ref="serviceAspect"><!-- 配置各种通知,method 属性值指定通知的方法名,pointcut-ref 属性引用切入点的  bean 的 id--><!-- 前置通知 --><aop:before method="before" pointcut-ref="myPointcut"/><!-- 注意:后置通知有一个 returning 属性对应方法返回值的参数名--><aop:after-returning method="afterReturning" pointcut-ref="myPointcut" returning="returnVal"/><!-- <aop:around>标签用于配置环绕通知,即在目标方法执行前后进行一些额外的处理。method="around"表示环绕通知的方法名是"around",这个方法需要在配置类中定义。pointcut-ref="myPointcut"表示引用了名为"myPointcut"的切点,即指定了目标方法的执行位置。 --><aop:around method="around" pointcut-ref="myPointcut"/><!-- <aop:after>标签用于配置最终通知,即在目标方法执行之后进行一些额外的处理。method="after"表示后置通知的方法名是"after",这个方法需要在配置类中定义。pointcut-ref="myPointcut"表示引用了名为"myPointcut"的切点,即指定了目标方法的执行位置。           --><aop:after method="after" pointcut-ref="myPointcut"/><!--  <aop:after-throwing>标签用于配置异常通知,即在目标方法抛出异常时进行一些额外的处理。method="afterThrowing"表示异常通知的方法名是"afterThrowing",这个方法需要在配置类中定义。pointcut-ref="myPointcut"表示引用了名为"myPointcut"的切点,即指定了目标方法的执行位置。throwing="e"表示在异常通知方法中传递了一个名为"e"的参数,用于接收目标方法抛出的异常。          --><aop:after-throwing method="afterThrowing" pointcut-ref="myPointcut" throwing="e"/></aop:aspect></aop:config></beans>

XML配置代码是使用Spring AOP来实现切面编程的示例。XML配置代码是使用Spring AOP来实现切面编程的示例。

<!-- 装配目标对象 -->
<bean id="userService" class="edu.nf.ch20.service.UserService"/>
<!-- 装配切面 -->
<bean id="serviceAspect" class="edu.nf.ch20.aspect.ServiceAspect"/>

在这个示例中,userService是一个具体的业务类,serviceAspect是一个切面类,用于包含横切关注点的逻辑。

继续,配置AOP:

<aop:config><!-- 配置切入点 --><aop:pointcut id="myPointcut" expression="execution(* edu.nf.ch20.service.UserService.*(..))"/><!-- 配置通知 --><aop:aspect ref="serviceAspect"><aop:before method="before" pointcut-ref="myPointcut"/><aop:after-returning method="afterReturning" pointcut-ref="myPointcut" returning="returnVal"/><aop:around method="around" pointcut-ref="myPointcut"/><aop:after method="after" pointcut-ref="myPointcut"/><aop:after-throwing method="afterThrowing" pointcut-ref="myPointcut" throwing="e"/></aop:aspect>
</aop:config>

<aop:config>标签中,首先定义了切入点(pointcut),用于确定哪些方法将被拦截。在这个示例中,切入点被命名为myPointcut,它使用了表达式语言来匹配edu.nf.ch20.service.UserService类的所有方法。

然后,通过<aop:aspect>标签配置了不同类型的通知(advice),包括<aop:before>(前置通知)、<aop:after-returning>(后置通知)、<aop:around>(环绕通知)、<aop:after>(最终通知)和<aop:after-throwing>(异常通知)。这些通知指向了切面类中对应的方法。

总结来说,这段XML配置代码实现了对edu.nf.ch20.service.UserService类的方法进行切面编程,并在不同的执行阶段触发对应的通知方法。这样可以将横切关注点的业务逻辑与核心业务逻辑分离,提高了代码的可维护性和可重用性。

具体来说,这段代码的作用如下:

  1. 配置目标对象和切面:通过配置<bean>元素,将目标对象和切面类实例化并装配到Spring容器中。目标对象是具体的业务类,而切面类包含了与横切关注点相关的逻辑。

  2. 配置切入点:使用<aop:pointcut>元素配置切入点,即确定哪些方法将被拦截和应用切面的逻辑。在这个示例中,切入点使用表达式execution(* edu.nf.ch20.service.UserService.*(..)),表示拦截edu.nf.ch20.service.UserService类的所有方法。

  3. 配置通知:通过<aop:before><aop:after-returning><aop:around><aop:after><aop:after-throwing>等元素,配置了不同类型的通知(advice)。这些通知指向切面类中的相应方法,并在目标对象的方法执行前、后、返回结果时、发生异常时等特定时机触发执行。

通过以上配置,可以实现以下主要功能:

  • 前置通知(Before Advice):在目标方法执行前执行切面中的方法,可以做一些准备工作、参数验证等操作。

  • 后置通知(After Advice):在目标方法执行后执行切面中的方法,可以进行一些清理工作、记录日志、统计时间等操作。

  • 环绕通知(Around Advice):在目标方法执行前后,或者替代目标方法执行,都可以执行切面中的方法。可以自由控制目标方法的执行,并进行一些额外的处理。

  • 最终通知(After-returning Advice):在目标方法正常返回结果后执行切面中的方法,可以对返回结果进行处理或记录日志。

  • 异常通知(After-throwing Advice):在目标方法发生异常时执行切面中的方法,可以处理异常、记录日志或进行补偿操作。

通过将横切关注点与核心业务逻辑分离,AOP提供了一种更加灵活和可维护的代码组织方式。它可以帮助开发人员在不改变原有业务逻辑的情况下,统一处理与业务无关的横切关注点,提高代码的可重用性、可维护性和可测试性。

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

 运行结果

 

 二、总结

上一章我们使用了MethodBeforeAdvice、AfterReturningAdvice、MethodInterceptor和ThrowsAdvice接口这四个接口去重写它们的方法来实现通知。这样有什么不好呢,每一次编写切面类的时候都需要实现这些接口,太繁重了,还有,重写异常通知时需要自己编写,而且方法名必须是afterThrowing,写错了还不行。

本章节通过使用 AspectJ ,我们自己来定义通知,自己编写。那么使用 AspectJ 的时候,可以实现接口重写他们的方法来实现通知,也可以自定义通知,它们有什么区别呢?

MethodBeforeAdvice、AfterReturningAdvice、MethodInterceptor和ThrowsAdvice接口是Spring框架中用于实现不同类型通知的接口。

  1. MethodBeforeAdvice:这个接口用于实现前置通知,即在目标方法执行之前被触发的通知。它的before方法会在目标方法执行前被调用,可以在该方法中添加需要执行的逻辑。

  2. AfterReturningAdvice:这个接口用于实现后置通知,即在目标方法成功返回后被触发的通知。它的afterReturning方法会在目标方法成功返回后被调用,可以在该方法中对返回结果进行处理或记录日志等操作。

  3. MethodInterceptor:这个接口用于实现环绕通知,即在目标方法的执行过程中进行拦截并控制其执行。它的invoke方法会在目标方法执行前后被调用,通过该方法可以手动控制目标方法的执行,包括传入参数、获取返回结果等。

  4. ThrowsAdvice:这个接口用于实现异常通知,即在目标方法抛出异常时被触发的通知。它没有定义具体的方法,而是通过在实现类中定义异常处理方法来实现不同类型异常的处理。

与自定义通知相比,这些接口提供了一种约定和规范化的方式来实现通知逻辑。开发者只需实现相应的接口,并将其配置到Spring容器中,框架会在合适的时机调用相应的方法。这种方式可以使通知与被拦截的目标方法解耦,并且能够与Spring的AOP功能无缝集成。

而自定义通知则更加灵活,开发者可以根据需要编写自己的通知类,不受特定接口的限制。自定义通知可以通过注解、切面表达式或者基于XML的配置来实现,具有更高的自由度和可定制性。开发者可以自己控制通知的触发时机和执行逻辑,更好地满足特定业务需求。

总之,使用Spring的通知接口可以快速实现常见类型的通知,并与Spring的AOP功能结合使用;而自定义通知则更加灵活,可以更好地满足自定义需求,但需要更多的开发额外处理。选择采用哪种方式取决于具体场景和需求。

 

三、gitee 案例

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

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

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

相关文章

idea中还原dont ask again

背景 在使用idea打开另外一个项目的时候&#xff0c;一不小心勾选为当前项目而且是不在下次询问&#xff0c;导致后面每次打开新的项目都会把当前项目关闭&#xff0c;如下图所示 下面我们就一起看一下如何把这个询问按钮还原回来 preferences/settings->Appearance&…

GPT实战系列-ChatGLM2部署Ubuntu+Cuda11+显存24G实战方案

GPT实战系列-ChatGLM2部署UbuntuCuda11显存24G实战方案 自从chatGPT掀起的AI大模型热潮以来&#xff0c;国内大模型研究和开源活动&#xff0c;进展也如火如荼。模型越来越大&#xff0c;如何在小显存部署和使用大模型&#xff1f; 本实战专栏将评估一系列的开源模型&#xf…

Photoshop 2024正式发布!内置最新PS AI,创意填充等功能无限制使用!

PS正式版目前更新到了2024&#xff0c;版本为25.0。 安装教程 1、下载得到安装包后&#xff0c;先解压。鼠标右键&#xff0c;【解压到当前文件夹】 2、双击 Set-up 开始安装 3、这里可以更改安装位置。如果C盘空间不够大&#xff0c;可以把它安装到C盘以外。更改好后&#x…

kafka安装

win10 来源:https://blog.csdn.net/tianmanchn/article/details/78943147 进入:http://kafka.apache.org/downloads.html点击Scala 2.12 - kafka_2.12-2.1.0.tgz点击http://mirrors.tuna.tsinghua.edu.cn/apache/kafka/2.1.0/kafka_2.12-2.1.0.tgz下载后解压缩 &#x1f604;:\…

【Bug】【内存相关】偶然发现一个内存溢出Bug复盘

一、问题 跑自动化用例的时候&#xff0c;uat-sg环境&#xff0c;发现SGW经常会返回 502 Bad Gateway响应 二、原因 经过SRE和BE Dev共同排查&#xff0c;502 是从ALB-- > 后端服务 后端服务无法响应导致&#xff0c;ALB会直接给客户端返回502。 服务端&#xff1a;由于c…

Typora +Picgo 搭建个人笔记

文章目录 Typora Picgo 搭建个人笔记一、Picgo Github 搭建图床1.基础设置2. 将配置导出&#xff0c;方便下次使用 二、Typora&#xff1a;设置 &#xff1a;1. 基本设置2. 导出自动提交3. 备份图片 Typora Picgo 搭建个人笔记 typora 下载地址&#xff1a; https://zahui.fan…

探索DeFi世界,MixGPT引领智能金融新时代

随着区块链技术的迅猛发展&#xff0c;DeFi&#xff08;去中心化金融&#xff09;正成为金融领域的新宠。在这个充满活力的领域里&#xff0c;MixTrust站在创新的前沿&#xff0c;推出了一款引领智能金融新时代的核心技术——MixGPT。 MixGPT&#xff1a;引领智能金融体验的大型…

Mac硬盘检测工具

Mac硬盘检测软件是一款用于检测和诊断Mac硬盘健康状态的工具&#xff0c;帮助用户及时发现潜在的硬盘问题&#xff0c;避免数据丢失和系统故障。通过全面的检测和报告功能&#xff0c;用户可以更好地了解自己的硬盘状况&#xff0c;确保数据的安全和可靠。给大家介绍几款好用的…

问题记录2 域名解析问题

上线部署时遇到内网域名解析问题&#xff1a; 内网域名为xxx.cn&#xff0c;在ip为yyy的服务器上&#xff0c;ping&#xff1a;xxx.cn 首先在服务器&#xff1a;yyy /etc/hosts查找缓存记录 cat /etc/hosts 127.0.0.1 VM-4-2-centos VM-4-2-centos 127.0.0.1 localhost.local…

初识容器Docker

目前使用 Docker 基本上有两个选择&#xff1a;Docker Desktop和Docker Engine。Docker Desktop 是专门针对个人使用而设计的&#xff0c;支持 Mac 和 Windows 快速安装&#xff0c;具有直观的图形界面&#xff0c;还集成了许多周边工具&#xff0c;方便易用。 不是太推荐使用D…

ASEMI-GBJ5010电源控制柜所用整流桥

编辑-Z 电源控制柜是一种常用的电力设备&#xff0c;广泛应用于工业生产过程中。在电源控制柜中&#xff0c;整流桥起着重要的作用。 整流桥是一种用于变流的电器元件&#xff0c;由4个二极管组成。它能够将交流电转换为直流电&#xff0c;并提供稳定的电源给控制柜中的其他设…

SpringBoot核心功能与基础配置

SpringBoot简介 原先的Spring程序缺点&#xff0c;包括依赖设置繁琐&#xff0c;每项jar的引用都需要自己撰写。并且配置繁琐&#xff0c;配置文件中也需要自己写加载bean等。由此针对原始的Spring程序&#xff0c;Pivotal团队提供的全新框架——SpringBoot&#xff0c;其设计…