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

文章目录

  • 1. 前言
  • 2. 什么是AOP
  • 3. AOP快速入门
  • 4. AOP的核心概念
  • 5. 切点表达式
  • 6. 切点函数
  • 7. 通知
  • 8. 总结

1. 前言

本文围绕AOP进行讲解,AOP可以做什么,涉及到了哪些注解,以及各个注解运行的时机,以及@Around相较于其它注解有什么不同,并且如果要执行目标方法需要怎么做

2. 什么是AOP

Spring的AOP(面向切面编程)是Spring框架的一个重要特性,它允许开发人员在应用程序中通过定义切面来实现横切关注点的功能,如日志记录、性能监控、事务管理等。AOP通过将这些关注点从业务逻辑中抽离出来,使得代码更加模块化、可维护和可重用。

SpringAOP就是批量对Spring容器中bean的方法做增强,并且这种增强不会与原来方法中的代码耦合

3. AOP快速入门

目标:要求service包下所有的类中的方法调用前输出: “方法被调用了”

在学AOP前,大家可能会在每个方法内添加一个输出语句. 但如果类很多,类中的方法也很多,添加起来也很麻烦,而且如果后续要进行修改,也很麻烦

  1. 首先要引入相关依赖:
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.3.29</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.7</version>
    </dependency>
</dependencies>    
  1. 把相关bean放到Spring容器中

可以使用注解@ComponentScan(basePackages = "com.example"),也可以在xml配置文件中,使用<context:component-scanbase-package="com.example"></context:component-scan>

在这里插入图片描述

因为我的代码结构是这样的,所以是com.example.

  1. 实现AOP

实现AOP可以使用注解,也可以使用xml配置文件. 因为是入门,所以先认识一下注解实现AOP的方式

①开启AOP注解支持

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

②创建切换类

其实就是普通的类,加上@Componentx @Aspect这两个注解而已

使用使用@Pointcut注解来指定要被强的方法
使用@Before注解来给我们的增湿代码所在的方法进行标识,并且指定了增强代码是在被增强方法执行之前执行
的。

示例:

@Component
@Aspect
public class MyAspect {
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void point(){

    }
    @Before("point()")
    public void methodBefore(){
        System.out.println("方法被调用了");
    }
}
@Pointcut("execution(* com.example.service.*.*(..))")

这段代码:是指 对com.example的service包下类的所有方法进行增强

 @Before("point()")
    public void methodBefore(){
        System.out.println("方法被调用了");
    }

@Before("point()")是指选中point()这个切点表达式的方法进行增强,增强的内容就是方法中的代码

UserService:

@Service
public class UserService {
    public void update(){
        System.out.println("执行了UserService的update方法");
    }
}

准备工作完成,进行测试.
在这里插入图片描述
可以看到在执行UserService的update()方法前,输出了"方法被调用了"

4. AOP的核心概念

  • Joinpoint (连接点): 所谓连接点是指那些可以被增强到的点。在spring中,这些点指的是方法,因为spring
    只支持方法类型的连接点
  • ⭐Pointcut (切入点) : 所谓切入点是指被增强的连接点(方法)
  • Advice (通知/ 增强) : 所谓通知是指具体增强的代码
  • Target (目标对象): 被增强的对象就是目标对象
  • Aspect (切面) : 是切入点和通知(引介) 的结合
  • Proxy (代理) : 一个类被 AOP 增强后,就产生一个结果代理类

5. 切点表达式

切点表达式用来表示要对哪些方法进行增强

写法: execution([修饰符] 返回值类型 包名.类名.方法名(参数))

  • 访问修饰符可以省略,大部分情况下可以省略
  • 返回值类型、包名、类名、方法名可以使用星号* 代表任意包
  • 名与类名之间一个点.代表当前包下的类,两个点..表示当前包及其子包下的类
  • 参数列表可以使用两个点..表示任意个数,任意类型的参数列表

如快速入门中的切点表达式:

execution(* com.example.service.*.*(..))

该切点表达式就是 对com.example的service包下类的所有方法进行增强,

6. 切点函数

我们也可以在要增强的方法上加上注解。然后使用@annotation来表示对加了什么注解的方法进行增强。

示例:

首先自定义一个注解,在创建类时选择Annotation
在这里插入图片描述

public @interface MyComment{
    
}

注意此时是不能直接用,我们需要添加几个注解
不知道添加什么也很好办,可以直接写一个注解,点击看源码
在这里插入图片描述

  • @Retention(RetentionPolicy.RUNTIME): 表示注解可以保持到什么时期,RUNTIME就是运行时
  • @Target({ElementType.METHOD}): 表示此注解可以添加到哪些东西方法,METHOD就是方法
    直接将注解添加到我们自定义的注解上即可

在这里插入图片描述
使用自定义注解,直接在相应的方法中添加即可:在这里插入图片描述
此时的切点就不能像之前那样写了,需要使用@annotation注解,并加上自定义注解的全类名
在这里插入图片描述
此时运行代码同样可以看到userService中的方法被增强了.
在这里插入图片描述
其实这种方式的AOP增强比使用切点表达式灵活多了.

7. 通知

SpingAOP的通知共有五种:

  • @Before: 前置通知在方法执行前执行
  • @AfterReturning: 返回后通知,在目标方法执行后执行,如果出现异常不会执行
  • @After: 后置通知,在目标方法返回结果之后执行,无论是否出现异常都会执行
  • @AfterThrowing: 异常通知,在目标方法抛出异常后执行
  • @Around: 环绕通知,围绕着方法执行

@Before,@AfterReturning和@After方法使用起来很简单,只需要知道加了这些注解的方法是在什么时候增强的即可

示例:

@Component
@Aspect
public class MyAspect {
    @Pointcut("@annotation(com.example.aspect.MyComment)")
    public void point(){

    }
    @Before("point()")
    public void methodBefore(){
        System.out.println("Before");
    }

    @AfterReturning("point()")
    public void methodAfterReturning(){
        System.out.println("AfterReturning");
    }

    @After("point()")
    public void methodAfter(){
        System.out.println("After");
    }
}
@Service
public class UserService {
    @MyComment
    public void update(){
        System.out.println("执行了UserService的update方法");
    }
}

在这里插入图片描述
注意:@AfterReturning 如果方法中异常不会执行❗

@AfterThrowing恰恰相反,只有出现异常才会执行

在切面类中增加 @AfterThrowing注解的方法

    @AfterThrowing("point()")
    public void methodAfterThrowing(){
        System.out.println("AfterThrowing");
    }

让需要增加的方法报错

@Service
public class UserService {
    @MyComment
    public void update(){
        System.out.println("执行了UserService的update方法");
        System.out.println(1/0);
    }
}

执行结果:
在这里插入图片描述

可以看到没有执行@AfterReturning相应的方法,而是执行了@AfterThrowing相应的方法

以上注解都比较简单,只需要知道他们运行的时机即可,重中之重还是@Around

切面类:

@Component
@Aspect
public class MyAspect {
    @Pointcut("@annotation(com.example.aspect.MyComment)")
    public void point(){

    }
    @Around("point()")
    public void methodAround(){
        System.out.println("Around");
    }
}

切点

@Service
public class UserService {
    @MyComment
    public void update(){
        System.out.println("执行了UserService的update方法");
    }
}

运行结果:
在这里插入图片描述

虽然执行了@Around相应的方法,但是结果中并没有UserService中的对应的输出语句,这是为什么? 这就是@Around的奇妙之处了

如果想要目标方法执行,需要添加一个ProceedingJoinPoint类型的参数,同时调用里面的proceed()方法:

@Around("point()")
public void methodAround(ProceedingJoinPoint joinPoint){
    System.out.println("Around");
    try {
        joinPoint.proceed();
    } catch (Throwable e) {
        throw new RuntimeException(e);
    }
}

此时就可以正常执行目标方法了
在这里插入图片描述
但@Around的用处远不止这些,它可以完成其它4个注解的作用

只需要添加@Around注解的相应方法这么改就可以了.

    @Around("point()")
    public void methodAround(ProceedingJoinPoint joinPoint){
        System.out.println("方法执行前");
        try {
            joinPoint.proceed();
            System.out.println("方法执行后");
        } catch (Throwable e) {
            System.out.println("方法出现异常");
            throw new RuntimeException(e);
        }finally {
            System.out.println("finally进行增强");
        }
    }

8. 总结

Spring的AOP基于代理模式实现,它使用代理对象(Proxy)来包装目标对象(Target),从而实现在目标对象的方法执行前、执行后或抛出异常时插入额外的逻辑。可以通过使用注解或配置文件来定义切面和切点,从而将横切关注点应用到目标对象的方法中。

Spring的AOP提供了一系列通知(Advice)类型,如前置通知(Before)、后置通知(After)、环绕通知(Around)、异常通知(AfterThrowing)和最终通知(AfterReturning),可以根据需要选择合适的通知类型来实现特定的横切关注点功能。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

群晖7.2版本通过Container Manager安装xiaoya-alist

小雅Alist&#xff0c;可以说是Alist应用中挂载阿里云最完美的成功案例。 一、下载镜像 注册表中下载镜像 Container Manager应该是7.2版本才改名&#xff0c;就是以前的docker。 打开【Container Manager】-【注册表】-【搜索框】搜索 xiaoya 内容区域&#xff0c;搜出的…

新零售系统平台解决方案 线上线下小程序怎么做

新零售线上线下解决方案是将传统零售业务与互联网科技相结合&#xff0c;通过数字化、智能化手段提升零售业务效率和用户体验的解决方案&#xff0c;它既有提供消费者线下体验&#xff0c;强调“稳”&#xff0c;又有互联网线上的“快”。 线上线下小程序可以通过一体化的进销存…

ubuntu20.04安装cv2

查看ubuntu的版本 cat /etc/lsb-release DISTRIB_IDUbuntu DISTRIB_RELEASE20.04 DISTRIB_CODENAMEfocal DISTRIB_DESCRIPTION"Ubuntu 20.04.3 LTS"更改镜像源 cp /etc/apt/sources.list /etc/apt/sources.list.bak cat > /etc/apt/sources.listdeb http://mirr…

第二证券:注册制退市规则?

跟着我国本钱商场不断发展和完善&#xff0c;持续注重退市原则改造也成为了商场中的热点话题。而注册制退市规矩的施行&#xff0c;无疑是新的退市原则下的一大重要内容。 首要&#xff0c;咱们需求了解什么是注册制退市规矩。所谓注册制退市规矩&#xff0c;指的是在注册制下…

App加固中的代码混淆功能,让逆向工程师很头疼

App加固中的代码混淆功能&#xff0c;让逆向工程师很头疼 “我想离开浪浪山。” 在数次尝试破解某个App 时&#xff0c;某个逆向工程师无奈感慨道。 逆向工程师顾名思义就是把一个个完整的软件逆推&#xff0c;还原成一段段代码&#xff0c;方便破解。 比如给他们一个手机Ap…

windows 使用WinSW制作服务

背景&#xff1a;最近维护老项目&#xff0c;需要使用windows server 2012 r2部署项目。使用springboot开发项目&#xff0c;nginx部署前端&#xff0c;于是打算把jar包和nginx都制作成服务 下载winsw地址&#xff1a;https://github.com/winsw/winsw/releases 下载这两个文件…

内衣迷你洗衣机什么牌子好?选购内衣裤洗衣机的方法

洗衣机在我们的生活中可谓是非常常见的了&#xff0c;几乎每家每户都具备着一台。即便是有洗衣机&#xff0c;也有不少人不会将自己我贴身衣物直接扔在洗衣机里清洗&#xff0c;而是会自己手工手洗。这跟我们传统上的观念有很大的关系&#xff0c;认为把内衣、内裤等贴身衣物放…

【23真题】发错试卷?想多了,只是题型大改!

今天分享的是23年南昌大学811的信号与系统试题及解析。南昌大学23年题型大改&#xff0c;加入了很多电路题目&#xff01;23考研的同学&#xff0c;甚至考场上以为发错试卷&#xff0c;考的电路原理。所以学有余力的同学&#xff0c;一定跟着我做各种院校的真题&#xff0c;见多…

华为 Mate 60 Pro 拆解:陆制零件比率上升至47% | 百能云芯

近日&#xff0c;日经新闻联合研究公司Fomalhaut Techno Solutions对华为 Mate 60 Pro 进行了拆解&#xff0c;揭示了这款于8月发布的新型智能手机的成本结构。拆解结果显示&#xff0c;该手机的国产零部件比例达到了47%&#xff0c;相较于三年前的 Mate 40 Pro&#xff0c;提高…

Js:获取最近6个月的月份(包含本月、不包含本月)

一、需求 获取最近6个月的月份&#xff08;不包含本月&#xff09;&#xff0c;比如现在是11月份&#xff0c;则需要获取到的月份是&#xff1a;10、9、8、7、6、5将月份从小到大排列 二、解决 1、获取最近的6个月份&#xff08;不包含本月&#xff09; var monthALL[]; …

欧盟铅镉RSL邻苯项目化学物质检测报告办理(RSL Report 资质)REACH 认证

如果您在亚马逊上销售商品&#xff0c;则必须遵守所有适用的欧盟和地方法律法规&#xff0c;以及适用于这些商品和商品信息的亚马逊政策。要在亚马逊上销售某些商品&#xff0c;)您需要向我们提供 REACH 符合性声明或检测报告。 RSL-Phthalate资质 欧盟RSL邻苯项目检测报告 Ph…

JVM jstat 查看内存新生代老年代回收情况,排查oom

jstat 命令 jstat - [-t] [-h] [ []] option&#xff1a;我们经常使用的选项有gc、gcutil vmid&#xff1a;java进程id interval&#xff1a;间隔时间&#xff0c;单位为毫秒 count&#xff1a;打印次数 每秒打印一次 jstat -gc 9162 1000S0C:年轻代第一个survivor的容量…

Kubernetes(k8s)介绍和环境部署

文章目录 Kubernetes一、Kubernetes介绍1.Kubernetes简介2.Kubernetes概念3.Kubernetes功能4.Kubernetes工作原理5.kubernetes组件6.Kubernetes优缺点 二、Kubernetes环境部署环境基本配置1.所有节点安装docker2.所有节点安装kubeadm、kubelet、kubectl添加yum源containerd配置…

用照片预测人的年龄【图像回归】

在图像分类任务中&#xff0c;卷积神经网络 (CNN) 是非常强大的神经网络架构。 然而&#xff0c;鲜为人知的是&#xff0c;它们同样能够执行图像回归任务。 图像分类和图像回归任务之间的基本区别在于分类任务中的目标变量&#xff08;我们试图预测的东西&#xff09;不是连续…

图片转excel表格怎么弄?有何密笈?

一般的软件要将图片转excel表格&#xff0c;都需要待识别的图片要有明显清晰的表格线&#xff0c;但金鸣识别则不需要这些条件的限制&#xff0c;即便是无表格线或缺少横线或竖线的图片&#xff0c;也能很好地识别成excel&#xff0c;另外&#xff0c;别的软件一般会限制文件大…

Windows Server 2012 R2系统服务器远程桌面服务多用户登录配置分享

Windows Server 2012系统在没有安装远程多界面的情况下&#xff0c;最多只能同时运行2个远程桌面&#xff0c;如果是有多个技术员、合伙人同时操作或是像游戏开发需要用到多界面&#xff0c;但是没有安装就很不方便&#xff0c;今天飞飞来和你们分享Windows server 2012R2系统远…

Python武器库开发-flask篇之模板渲染(二十四)

flask篇之模板渲染(二十四) Flask 中的模板是一种将数据和 HTML 代码组合在一起的方式&#xff0c;使得我们可以生成动态的 HTML 页面。使用模板可以使我们的代码更加简洁、易于维护和复用。在真实的环境中&#xff0c;我们往往接触到的是由 html、CSS和JavaScript所做的网页&…

51单片机应用从零开始(四)

51单片机应用从零开始&#xff08;一&#xff09;-CSDN博客 51单片机应用从零开始&#xff08;二&#xff09;-CSDN博客 51单片机应用从零开始&#xff08;三&#xff09;-CSDN博客 详解 KEIL C51 软件的使用建立工程-CSDN博客 详解 KEIL C51 软件的使用设置工程编绎与连接程序…

三种跨域解决方案:HttpClient、注解、网关

注解&#xff1a;CrossOrigin网关整合Httpclient 为什么会有跨域问题 因为浏览器的同源政策&#xff0c;就会产生跨域。比如说发送的异步请求是不同的两个源&#xff0c;就比如是不同的的两个端口或者不同的两个协议或者不同的域名。由于浏览器为了安全考虑&#xff0c;就会产…

穿越时空:未来云计算的奇妙世界

文章目录 1. 云计算与智能家居2. 云计算与无人驾驶3. 云计算与虚拟现实4. 云计算与人工智能未来展望 &#x1f389;欢迎来到云计算技术应用专栏~穿越时空&#xff1a;未来云计算的奇妙世界 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff1a;IT陈寒的博客&am…