Spring framework Day21:Spring AOP 注解结合配置类示例

前言

Spring AOP是一种强大的面向切面编程工具,它能够帮助我们更好地处理与核心业务逻辑无关的横切关注点。通过使用注解和配置类的方式,我们可以更加简洁和灵活地实现AOP。

本文将以一个示例来介绍如何结合注解和配置类来使用Spring AOP。通过这个示例,你将了解如何使用注解来定义切点、通知和切面,并通过配置类来启用和配置AOP。

前面三章我们都是通过 xml 文件去配置,那么这章我们开始使用 Java 配置类加注解来完成案例。

注意:使用 xml 是为了让大家了解 xml 怎么去配置,现在常用的都是注解加 Java 配置类来实现。

在开始之前,请确保你已经具备了Spring框架的基础知识,并且已经正确配置了Spring环境。

接下来,我们将一步步地介绍这个示例,让我们开始吧!

一、开始学习

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
@Service
public class UserService {/*** 目标方法,也就是需要被增强的方法* 因此它就是一个连接点* @param name*/public String add(String name){log.info("添加用户..." + name);return "success";}}
4、在 aspect 包下新建一个 UserAspect 切面类
@Slf4j
// 将切面纳入容器管理
@Component
/*** 使用 @Aspect 注解标识当前类为一个切面*/
@Aspect
public class UserAspect {@Pointcut("execution(* edu.nf.ch21.service.UserService.*(..))")public void pointcut() {}@Before("pointcut()")public void before(JoinPoint jp) {log.info("前置通知");}/*** 后置通知** @param jp* @param returnVal*/@AfterReturning(value = "pointcut()", returning = "returnVal")public void afterReturning(JoinPoint jp, Object returnVal) {log.info("后置通知,目标方法返回值:" + returnVal);}/*** 环绕通知** @param jp* @return*/@Around("pointcut()")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*/@AfterThrowing(value = "pointcut()", throwing = "e")public void afterThrowing(JoinPoint jp, Exception e) {log.info("异常通知:" + e.getMessage());}/*** 最终通知* @param jp*/@After("pointcut()")public void after(JoinPoint jp){log.info("最终通知");}}

这个切面类定义了一个pointcut()切点方法,用于指定哪些方法需要被拦截。这里使用了execution()表达式来匹配edu.nf.ch21.service.UserService类中的所有方法。

接下来,针对这个切点方法,定义了五个通知方法:

  • before()方法是一个前置通知,在目标方法执行之前执行,并且拦截到JoinPoint参数,可以获取目标方法的信息。
  • afterReturning()方法是一个后置通知,在目标方法正常返回时执行,拦截到JoinPoint和目标方法的返回值returnVal参数。
  • around()方法是一个环绕通知,可以在目标方法执行前、执行后都做一些处理,并拦截到ProceedingJoinPoint参数,可以手动调用目标方法并获取返回值。
  • afterThrowing()方法是一个异常通知,在目标方法抛出异常时执行,拦截到JoinPointException参数。
  • after()方法是一个最终通知,在目标方法执行结束后(包括正常结束和异常结束)执行,拦截到JoinPoint参数。

 其中还使用了很多的注解,它们分别是什么意思?

  1. @Component: 这是Spring框架的注解之一,用于将类标识为一个可被Spring容器扫描和管理的组件。在这个示例中,@Component注解表示将UserAspect类作为一个切面组件纳入到Spring容器中。

  2. @Aspect: 这是AspectJ框架的注解,用于标识一个类为切面。切面是一个包含了各种通知和切点的类,用于对其他类中的方法进行拦截和增强。

  3. @Pointcut: 这是一个自定义的方法级别注解,用于定义一个切点。切点决定了哪些方法会被拦截和应用切面逻辑。在这个示例中,pointcut()方法使用了@Pointcut注解来定义切点。

  4. @Before: 这是一个前置通知注解,用于在目标方法执行之前执行某段逻辑。在这个示例中,before()方法使用了@Before注解,表示在匹配到的方法执行之前会执行before()方法中的逻辑。

  5. @AfterReturning: 这是一个后置返回通知注解,用于在目标方法正常返回时执行某段逻辑。在这个示例中,afterReturning()方法使用了@AfterReturning注解,并通过value属性指定了切点,returning属性指定了目标方法返回值的参数名,表示在匹配到的方法正常返回时会执行afterReturning()方法中的逻辑。

  6. @Around: 这是一个环绕通知注解,用于在目标方法执行前和执行后执行某段逻辑。在这个示例中,around()方法使用了@Around注解,并通过value属性指定了切点,表示在匹配到的方法执行前后会执行around()方法中的逻辑。注意,around()方法的参数类型为ProceedingJoinPoint,可以手动调用目标方法。

  7. @AfterThrowing: 这是一个异常通知注解,用于在目标方法抛出异常时执行某段逻辑。在这个示例中,afterThrowing()方法使用了@AfterThrowing注解,并通过value属性指定了切点,throwing属性指定了异常的参数名,表示在匹配到的方法抛出异常时会执行afterThrowing()方法中的逻辑。

  8. @After: 这是一个最终通知注解,用于在目标方法执行结束后执行某段逻辑,无论是否抛出异常。在这个示例中,after()方法使用了@After注解,并通过value属性指定了切点,表示在匹配到的方法执行结束后会执行after()方法中的逻辑。

总结起来,这些注解一起使用可以实现对目标方法的拦截和增强,例如在方法执行前后打印日志、记录返回值、处理异常等。

5、在 config 包下新建一个  AppConfig 配置类
@Configuration
@ComponentScan(basePackages = "edu.nf.ch21")
// 启用 AspectJ 注解处理器
// proxyTargetClass 指定为 true 表示强制使用 cglib 生成代理
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AppConfig {
}

这段代码是一个Spring配置类,用于配置Spring容器和启用AspectJ注解处理器。下面是对每个注解的解释:

  • @Configuration: 这是一个Spring框架的注解,用于表示该类是一个配置类。配置类通常用于定义Bean的创建和配置,以及其他的Spring配置。

  • @ComponentScan: 这是一个Spring框架的注解,用于指定要扫描的包或类的路径。在这个示例中,basePackages属性指定了要扫描的基础包路径为"edu.nf.ch21",意味着Spring容器会扫描并加载该包及其子包中的组件。

  • @EnableAspectJAutoProxy: 这是一个Spring框架的注解,用于启用AspectJ注解处理器,并开启基于AspectJ的自动代理功能。proxyTargetClass = true表示使用cglib生成代理对象而不是默认的基于接口的JDK动态代理方式。

这些注解的组合作用是将该配置类纳入Spring容器的管理,并启用AspectJ注解处理器和自动代理功能,从而实现AOP(面向切面编程)的特性。

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

 运行结果

使用注解开发,效率是不是很高,没错,在实际开发中注解和 Java 配置类确实是很开。也是开发中最常用的一种,当然 xml 也可以,只不过是使用 Java 配置类加注解开发会比较好看,阅读性好。大家根据自己的选择使用,推荐使用的是这种方法。

 

二、使用Spring AOP 注解结合配置类和使用 xml 有什么区别

使用Spring AOP注解和配置类与使用XML方式定义AOP有以下区别:

  1. 配置方式:使用注解的方式是通过在代码中添加注解来定义切面、切点和通知等,而使用XML方式是通过编写XML配置文件来定义AOP元素。

  2. 代码可读性:使用注解方式可以直接在Java代码中看到AOP相关的配置,使得代码更加紧凑和可读。而使用XML方式需要打开独立的XML配置文件,可能会增加代码的复杂性。

  3. 配置灵活性:使用注解方式可以更灵活地进行配置,可以直接将切面和通知应用于具体的类或方法,也可以使用通配符来匹配一组类或方法。而使用XML方式则需要在配置文件中明确指定切入点和通知的目标。

  4. IDE支持:使用注解方式可以充分利用现代IDE的代码提示和自动补全功能,提升开发效率。而使用XML方式则需要手动编写XML配置文件,可能会增加书写错误的风险。

  5. 集成和维护:使用注解方式可以更加方便地进行代码集成和版本控制,同时也更容易进行维护和重构。而使用XML方式则可能导致配置文件随着系统变得越来越庞大和难以管理。

总的来说,注解方式相对于XML方式更加简洁、灵活和方便于代码维护,但对于复杂的AOP配置或需要与第三方库进行集成的情况,XML方式可能更为适用。选择使用哪种方式还取决于个人或团队的偏好和具体的项目需求。

三、gitee 案例

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

 

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

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

相关文章

Windows 钉钉多开 dingtalkRC版

亲测可用 下载链接&#xff1a; https://dtapp-pub.dingtalk.com/dingtalk-desktop/win_installer/RC/DingTalk_v6.5.20-RC.7229101.exe

Redis消息队列

Redis是一个支持消息队列功能的内存数据库&#xff0c;可以作为消息队列系统使用。 基于List结构模拟消息队列 消息队列&#xff08;Message Queue&#xff09;&#xff0c;字面意思就是存放消息的队列。而Redis的list数据结构是一个双向链表&#xff0c;很容易模拟出队列效果…

徐建鸿:深耕中医康养的“托钵行者”

为什么是“庄人堂”&#xff1f;杭州“庄人堂”医药科技公司董事长徐建鸿很乐意和别人分享这个名称的由来&#xff0c;一方面是庄子首先提出“养生”这个概念&#xff0c;接近上工治未病的上医&#xff0c;取名“庄人堂”代表庄子门生&#xff0c;向古哲先贤致敬&#xff01;另…

Go 泛型解密:从基础到实战的全方位解析

Go泛型解密 一、概述 泛型编程是计算机科学中一个相当重要的概念&#xff0c;广泛应用于各种编程语言和框架中。在Go语言中&#xff0c;泛型的讨论和实现也走了一段相对漫长的路。这一路上既有激烈的讨论&#xff0c;也有种种的尝试和迭代。本节将对泛型的基础概念进行深入分析…

基于SSM+Vue的咖啡销售系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

菜鸟智谷产业园正式开园!入驻企业可享受“城区+园区”双重政策扶持

位于杭州未来科技城的菜鸟智谷产业园正式开园了! 杭州未来科技城发布新电商产业加速“百千万亿”计划,菜鸟智谷产业园发布“产业赋能计划”,并设立天猫品牌孵化基地,落户中国(杭州)跨境电商综试区一带一路电商运营中心,引入悦汇跨境产业创新基金……10月17日,杭州未来科技城(海…

SpringBoot+SpringSecurity项目的创建

首先创建一个springboot项目&#xff0c;注意springboot要求jdk版本在17以上 等项目构建完成之后&#xff0c;在pom文件中加入SpringSecurity的依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-securi…

Linux基础命令(二)

1.ls命令 命令格式&#xff1a; ls -a -l -h Linux路径 &#xff08;1&#xff09; 直接使用ls&#xff0c;不加选项和参数。 ls 将会以平铺形式&#xff0c;列出当前文件夹下的内容&#xff1a; &#xff08;2&#xff09;加上参数 ls / 将会列出/目录下的内容。 -a选项…

JVM垃圾回收算法介绍

堆的分代和区域 &#xff08;年轻代&#xff09;Young Generation&#xff08;eden、s0、s1 space&#xff09; Minor GC &#xff08;老年代&#xff09;Old Generation &#xff08;Tenured space&#xff09; Major GC|| Full GC &#xff08;永久代&#xff09;Permanent…

关注用户信息卡片

效果展示 CSS 知识点 box-shadow 属性回顾CSS 变量回顾 实现页面整体布局 <div class"card"><div class"box"><!-- 视频 --><div class"vide_box"><video src"user.mp4" type"video/mp4" aut…

UDP与TCP协议

很抱歉&#xff0c;我之前写好的UDP与TCP文章不小心被删了&#xff0c;所以&#xff0c;这篇文章只有一半&#xff0c;后面我会尽快补全。 在完成HTTPS的学习后&#xff0c;我们就完成了应用层的所有讲解&#xff0c;下面我们开始讲解传输层&#xff0c;这一层常用的协议为TCP…

什么是CSGO大行动,2023年CSGO大行动时间预测

什么是CSGO大行动&#xff0c;2023年CSGO大行动时间预测 什么是CSGO大行动&#xff0c;2023年CSGO大行动时间预测 那天群里在提大行动&#xff0c;不明所以的新同学在问&#xff0c;什么是大行动&#xff0c;是不是官方红锁大行动要来了&#xff1f;当然不是&#xff0c;别自己…

面试十分钟不到就被赶出来了,问的实在是太变态了...

从外包出来&#xff0c;没想到算法死在另一家厂子 自从加入这家公司&#xff0c;每天都在加班&#xff0c;钱倒是给的不少&#xff0c;所以也就忍了。没想到8月一纸通知&#xff0c;所有人不许加班&#xff0c;薪资直降30%&#xff0c;顿时有吃不起饭的赶脚。 好在有个兄弟内…

云计算:掌控未来,一触即发!

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是尘缘&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f449;点击这里&#xff0c;就可以查看我的主页啦&#xff01;&#x1f447;&#x…

springboot时间管理系统springboot47

大家好✌&#xff01;我是CZ淡陌。一名专注以理论为基础实战为主的技术博主&#xff0c;将再这里为大家分享优质的实战项目&#xff0c;本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#xff0c;希望你能有所收获&#xff0c;少走一些弯路…

从培训班出来之后找工作的经历,教会了我五件事.....

我是非计算机专业&#xff0c;由于专业不好实习急着就业有过一些失败的工作经历后&#xff0c;跑去参加培训进入IT这行的。 之前在报名学习软件测试之前我也很纠结&#xff0c;不知道怎么选择机构。后面看到有同学在知乎上分享自己的学习经历&#xff0c;当时对我的帮助很大。…

美芯片禁令再次扩大,波及英伟达、AMD以及intel等科技公司 | 百能云芯

拜登政府17日宣布&#xff0c;计划停止英伟达&#xff08;Nvidia&#xff09;、超微半导体以及英特尔等科技公司设计的先进AI芯片输出中国大陆&#xff0c;英伟达&#xff08;Nvidia&#xff09;昨日股价重挫4.68%至每股439.38美元&#xff1b;天风国际证券分析师郭明錤表示&am…

Elasticsearch介绍及插件head和kibana下载

目录标题 一、Elasticsearch介绍二、Elasticsearch下载三、Elasticsearch-head四、Elasticsearch-kibana 一、Elasticsearch介绍 Elasticsearch是什么? Elasticsearch 是一个基于Lucene的分布式搜索和分析引擎&#xff0c;ES是elaticsearch简写&#xff0c;Elasticsearch是一…

解决vue3 + vite + ts 中require失效的问题(require is not defind)

require is not defind因为require是属于webpack的方法&#xff0c;vite中找不到这个方法肯定报错 解决办法 通过vite官网了解到新的引入方式&#xff0c;我使用了其中一种 imgList: [{name: "lj",src: new URL(../../assets/img/applyList.png, import.meta.url).…

图像检索算法 计算机竞赛

文章目录 1 前言2 图像检索介绍(1) 无监督图像检索(2) 有监督图像检索 3 图像检索步骤4 应用实例5 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 图像检索算法 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff…