JavaEE进阶:SpringAOP

一.AOP概述

在学习完Spring的统一功能之后,我们就要进入到SpringAOP的学习.

AOP是Spring框架的第二大核心.

AOP,全名叫Aspect Oriented Programming,翻译过来就是面向切面编程

简单来说AOP是一种思想,是对某一类事情的集中处理

就好比之前学过的拦截器,就是登入校验这一类问题的统一处理.

还有统一结果返回,统一异常处理,这些都算做AOP的实现.

但是spring考虑不到所有的情况,所以有些情况下需要自己实现AOP.

比如我现在要记录每个方法耗时的时间,又或者有别的什么需求.

二.SpringAOP快速入门

假如不使用AOP,我们要记录每个方法的运行时间,就需要在方法开头记个时间戳,然后return前记录个时间戳然后求差.这样子每个方法都得去写,不仅麻烦,还容易漏.

接下来我们用AOP来解决这个问题.

2.1 引入AOP依赖

在pom.xml文件中添加依赖

java 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.2 编写AOP程序

记录controller中的每个方法的执行时间.

AOP程序,主要通过@Aspect注解和@Around注解来实现.

@Aspect注解是用来告诉spring这是一个切面类.

@Around注解表示环绕通知,在目标方法前后都会被执行.括号内的内容表示对哪些方法进行功能增强(作用范围).

ProceedingJoinPoin.proceed()方法表示让原始方法执行.

接下来我们测试一下.

运行接口就能看到每个controller方法的耗时了.

三.SpringAOP详解

3.1 SpringAOP核心概念

3.1.1 切点

切点的作用就是来告诉程序对哪些方法进行增强,也就是AOP的作用范围.

下面这个就是切点表达式

3.1.2 连接点

所有满足切点表达式的方法,都叫做连接点,

以上面切点表达式为例,所有com.example.demo.controller下的方法都是连接点.

3.1.3 通知

通知就是具体要做的工作,指那些重复的逻辑,也就是共同的功能.

比如在上述程序中,记录方法的耗时,就是通知.

在AOP面向切面编程中,我们把这部分重复代码逻辑抽出来单独定义,这部分代码就是通知的内容.

3.1.4 切面

切面 = 切点+通知

通过切面能描述当前AOP程序的作用范围和进行什么样的的操作

下面这个就是切面

3.2通知类型

通知不止有@Around一种类型.@Around是环绕通知,就是在目标方法前后都执行.

SpringAOP的通知类型有以下几种:

我们来看下这些通知的执行顺序

java 复制代码
public class AspectDemo {
    @Around("execution(* com.example.demo.controller.*.*(..))")
    public Object AroundDemo(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("Around方法开始执行");
        Object result = joinPoint.proceed();
        log.info("Around方法执行完毕");
        return result;
    }

    @Before("execution(* com.example.demo.controller.*.*(..))")
    public void BeforeDemo() throws Throwable {
        log.info("Before方法执行");
    }

    @After("execution(* com.example.demo.controller.*.*(..))")
    public void AfterDemo() throws Throwable {
        log.info("After方法执行");
    }

    @AfterReturning("execution(* com.example.demo.controller.*.*(..))")
    public void AfterReturningDemo() throws Throwable {
        log.info("AfterReturning方法执行");
    }
    @AfterThrowing("execution(* com.example.demo.controller.*.*(..))")
    public void AfterThrowingDemo() throws Throwable {
        log.info("AfterThrowing方法执行");
    }
}

运行登入接口程序,观察日志

可以看到在正常情况下.AfterThrowing方法不会被执行,现在看看抛出异常的情况

可以看到在异常情况下Around执行只会执行一半,这个不是绝对的,如果在finally里面写,也是会执行的.

注意:

3.3@PointCut

上述代码存在一个问题,就是存在大量的切点表达式.

Spring提供了**@PointCut注解,把公共的切点表达式提取出来,在需要使用的时候在引入即可.**

使用pt()来表示切点表达式,这样在之后使用的时候不需要写那么多,同时在需要修改的时候,只需要改一处即可.

当切点定义使用private修饰的时候,只能在当前切面类使用,如果其他切面类也要使用切点定义,就需要将private改为public.引用方式为:全限定类名.方法名()

3.4切面优先级@Order

当我们一个项目中定义了多个切面类的时候,并且这些切面类同时匹配到了同一个方法,这时候这些切面类的顺序会是什么样子?

我们来定义三个切面类.

此时,运行程序,访问接口.可以看到还是有顺序的,这个顺序是按照字母和数字来排序的.

但是我们的类名还是有更多的意义,所以不方便随意改动,此时又想要按照我们想的顺序来执行,就需要用到@Order注解.

再次运行程序.可以看到此时顺序发生变化了.

从这个结果来看,@Order里面的数字越小,执行顺序越优先.

3.5 切点表达式

上述代码中,我们一直在使用切点表达式来描述切点,下面我们来介绍一下切点表达式的语法.

1.execution(......):根据方法的签名来匹配

2.@annotation(......):根据注解匹配

3.5.1 execution表达式

execution()是最常用的切点表达式,用来匹配方法.

语法:

3.5.2 @annotation

execution表达式更适用于有规则的,就好比某个包下面的所有类,或者同一个名字的包,类...

@annotation注解就不同了,他可以适用于无规则的多个方法

举个简单的例子,我们可以自定义一个注解,然后让加上这个注解的方法实现AOP

3.5.2.1 自定义注解@MyAspect

创建一个注解类

然后用**@Target表示Annotation所修饰的对象范围**,也就是说这个注解可以用在方法上还是类上.

@Retention注解指Annotation被保留的时间长短,也就是注解的生命周期

此时就已经定义完一个注解了.

3.5.2.2 切面类

定义完注解之后,我们需要使用@annotation切点表达式定义切点,只对@MyAspect注解生效.

我们需要把@Around注解里面的切点表达式改成

此时,只有加了@MyAspect注解的方法才能记录耗时.

分别运行t1,t2,可以看到只有加了@MyAspect注解的方法才能生效

相关推荐
leikooo4 小时前
用餐厅和盘子理解栈和堆
java·数据结构·链表·rust
Ivanqhz5 小时前
激活函数在 Transformer 中的作用及各种变体简述
java·linux·数据库·人工智能·深度学习
沙漠之主5 小时前
C++编程教学设计资料:从入门到实战的完整课程方案
java·前端·c++
FPGA小徐5 小时前
PA1 基础设施(2)深度解析:NEMU 中 ITRACE、MTRACE、FTRACE、IRINGBUF、ETRACE、DIFFTEST 全解析
java·服务器·网络
YOLO数据集集合6 小时前
EvoAgent:面向PR研发治理的自进化Multi-Agent Harness系统
java·开发语言·目标检测·agent·自进化
知行EDI6 小时前
知行之桥 MaBang 端口使用指南——Create Order 订单创建篇
java·服务器·数据库
笑鸿的学习笔记6 小时前
C++笔记之大块顺序写
java·c++·笔记
打工仔折腾 AI6 小时前
从 Demo 到生产级 Agent:8 个关键设计机制与 Python 实现拆解
java·jvm·人工智能·后端·python·langchain·ai agent 实战
殷色玫瑰7 小时前
C/C++ 内存管理详解:从内存分布到 new/delete 底层原理
java·linux·c语言·c++
青山木9 小时前
Hot 100 --- 编辑距离
java·数据结构·算法·leetcode·动态规划