Spring AOP 的实现及原理

目录

  • [什么是 Spring AOP ?](#什么是 Spring AOP ?)
    • [AOP 是啥 ?](#AOP 是啥 ?)
    • [Spring AOP 可以干啥 ?](#Spring AOP 可以干啥 ?)
  • [AOP 的组成](#AOP 的组成)
  • [Spring AOP 的实现](#Spring AOP 的实现)
  • [Spring AOP 的实现原理](#Spring AOP 的实现原理)

什么是 Spring AOP ?

AOP 是啥 ?

我们知道 OOP 是面向对象编程, 那 AOP 又是啥呢 ?

AOP(Aspect Oriented Programming):⾯向切⾯编程,它是⼀种思想,它是对某⼀类事情的集中处理。

什么又是面向切面编程?

就比如:我上 CSDN 发布文章时,它会先查询我的登录状态,我查询个人文章列表时,也要查询登录状态,查看个人主页也一样,这些功能的共同点是查询登录状态,那判断用户是否登录这件事,它就是一个切面,他就是某一类事,面向切面编程就是面向某一类事进行编程,将某一类事集中处理了。(这样就可以把精力放在业务逻辑上,而不是编写重复代码)

AOP 是⼀种思想,⽽ Spring AOP 是⼀个框架,提供了⼀种对 AOP 思想的实现,它们的关系和 IoC 与 DI 类似。

Spring AOP 可以干啥 ?

统一用户登录判断

统一日志记录

统一方法执⾏时间统计

统⼀的返回格式设置

统⼀的异常处理

事务的开启和提交等等

AOP 是针对某一类通用的事件进行统一处理,它是 OOP 的一种补充。

AOP 的组成

  1. 切面 (Aspect):定义的是什么事件(AOP 是干什么的,比如:是用户登录校验)

  2. 切点 (Pointcut):定义具体规则(定义用户拦截规则,比如:哪些接口需要判断用户登录,哪些接口不需要判断)

  3. 通知 (Advice):AOP 执行的具体方法(比如:获取用户登录信息,获取到则说明已登录)

通知又分为以下几种:

前置通知 @Before:通知⽅法会在⽬标⽅法调⽤之前执⾏。

后置通知 @After:通知⽅法会在⽬标⽅法返回或者抛出异常后调⽤。

返回通知 @AfterReturning:通知⽅法会在⽬标⽅法返回后调⽤。

异常通知 @AfterThrowing:通知⽅法会在⽬标⽅法抛出异常后调⽤。

环绕通知 @Around:通知包裹了被通知的⽅法,在被通知的⽅法通知之前和调⽤之后执行自定义的行为。

  1. 连接点 (Join Point):所有可能触发切点的点(比如:所有接口)

Spring AOP 的实现

  1. 添加 Spring AOP 依赖:
java 复制代码
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-bo
ot-starter-aop -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
  1. 定义切面:
java 复制代码
@Aspect  //表明此类为一个切面
@Component   // 随着spring框架启动而启动
public class UserAspect {
 
}
  1. 定义切点:
java 复制代码
@Aspect  //表明此类为一个切面
@Component   // 随着spring框架启动而启动
public class UserAspect {
	// 切点,这⾥使⽤ AspectJ 表达式语法
	//拦截 UserController 里所有方法
    @Pointcut("execution(* com.example.demo.controller.UserController.* (..))")
    public void pointcut(){   
    }
}
  1. 执行通知:

先将被拦截的类实现:

java 复制代码
@RestController
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/getuser")
    public String getUser() {
        System.out.println("do getUser");
        return "get User";
    }

    @RequestMapping("/deluser")
    public String delUser() {
        System.out.println("do delUser");
        return "del User";
    }
}
java 复制代码
@Aspect  
@Component   
public class UserAspect {
    @Pointcut("execution(* com.example.demo.controller.UserController.* (..))")
    public void pointcut(){
    }

    //该前置通知针对于这个切点
    @Before("pointcut()")
    public void doBefore() {
        System.out.println("执行了前置通知");
    }
}


确实是先执行前置通知,再执行被拦截的方法。

再来执行个后置通知:

java 复制代码
    @After("pointcut()")
    public void doAfter() {
        System.out.println("执行了后置通知");
    }

再次访问:

环绕通知:

java 复制代码
    // 添加环绕通知
    @Around("pointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint){
        Object obj = null;
        System.out.println("Around ⽅法开始执⾏");
        try {
            // 执⾏目标⽅法
            obj = joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("Around ⽅法结束执⾏");
        return obj;
    }


环绕通知是在最前面和最后面执行的。(在多线程中可以统计目标方法的执行时间,单线程下也可以使用前置通知和后置通知来统计)

Spring AOP 的实现原理

Spring AOP 是构建在动态代理基础上,因此 Spring 对 AOP 的⽀持局限于⽅法级别的拦截。

Spring 动态代理组成:

  1. JDK Proxy(代理对象必须实现接口,才能使用 JDK Proxy)

  2. CGLIB(通过实现代理类的子类来实现动态代理,被 final 修饰的类不能被代理)
    JDK Proxy 和 CGLIB 区别:

  3. 实现不同:DK Proxy 要求代理类实现接口才能被代理,CGLIB 通过实现代理类的子类来实现动态代理

  4. 性能不同:JDK 7+ JDK Proxy 的性能高于 CGLIB,JDK 7 前则低于

相关推荐
Haoea!4 分钟前
JDK21新特性-序列集合
java
快乐非自愿13 分钟前
Java函数式接口——渐进式学习
java·开发语言·学习
wanghowie20 分钟前
01.01 Java基础篇|语言基础与开发环境速成
java·开发语言
白露与泡影22 分钟前
2026年Java面试题目收集整理归纳(持续更新)
java·开发语言·面试
鹿角片ljp26 分钟前
Spring Boot Web入门:从零开始构建web程序
前端·spring boot·后端
百***787530 分钟前
【技术教程】3步极速接入GPT-5.1:零门槛体验多模态AI能力
android·java·人工智能·gpt·opencv
默 语37 分钟前
IPIDEA 代理技术在海外品牌社媒数据采集中的实操落地(Instagram 营销分析案例版)
java·人工智能·ai·ai编程
墨痕诉清风41 分钟前
java漏洞集合工具(Struts2、Fastjson、Weblogic(xml)、Shiro、Log4j、Jboss、SpringCloud)
xml·java·struts·安全·web安全·spring cloud·log4j
程序员阿鹏43 分钟前
SpringBoot自动装配原理
java·开发语言·spring boot·后端·spring·tomcat·maven
Andy工程师44 分钟前
一个接口可以有多个实现类
java