Spring AOP

AOP思想

AOP指的是面向切面编程,跟OOP面向对象编程一样是一种思想。用一句话概括就是:在面对某一类问题时,主动进行集中处理。

例如在博客系统中,在添加博客,删除博客等场景需要验证你的身份信息,是否已经登入。以往的做法是把验证是否登入功能的代码进行封装,然后在这些板块调用它。但是这就把代码嵌入到这些板块中,耦合度高。如果未来验证是否登入功能的代码进行修改,需要传递参数变了,那么整个项目调用它的板块也要进行修改,维护成本高。而AOP就可以很好的解决这个问题,把验证用户是否登入集中处理,在添加博客,删除博客时会主动帮你处理这个问题,这就让这些板块都只完成自己的要实现的功能,耦合度就降低了。

AOP的组成

切面

通俗理解切面就是程序中一个处理某方面具体问题的一个类,类中包含很多方法,这些方法就是切点和通知

切点

配置主动拦截规则

在博客系统中,添加博客,删除博客等功能中需要验证是否用户登入,而登入功能却不需要,判断一个需不需要就是通过你配置的拦截规则来判断,如果需要就主动帮你处理。

通知

经过拦截规则的判定,如果被拦截下来,后续要实现哪些具体业务代码。

  1. 前置通知:在执行目标方法之前执行的方法
  2. 后置通知:在执行目标方法之后执行的方法
  3. 异常通知:在执行目标方法出现异常时,执行的通知
  4. 返回通知:目标方法执行了返回数据(return)时,执行的通知
  5. 环绕通知:在目标方法执行的周期内(执行之前,执行中,执行后)都可以执行的方法叫做环绕通知
连接点

可能触发AOP拦截规则的所有点(所有请求)

Spring AOP的实现

添加Spring AOP框架支持
xml 复制代码
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
			<version>2.7.9</version>
		</dependency>
定义切面和切点
java 复制代码
@Aspect //告诉框架我是一个切面类
@Component //随着框架的启动而启动
public class UserAop {
}
java 复制代码
public class UserAop {
    /*
    定义切点,配置主动拦截规则
		execution()切点函数,用来匹配具体哪个方法
     */
    @Pointcut("execution(* com.example.demo.controller.UserController.*(..))")
    public void pointcut() {
    }
}
拦截规则的配置

execution(<修饰符><返回类型><包.类.方法(参数)><异常>)

  1. 修饰符,一般省略
  2. 返回值,不能省略
    1. void 返回没有值
    2. String 返回字符串
      • 任意
    1. com.example.demo.*.service demo包下任意一个包(该包的下一层是service)
    2. com.example.demo... demo包下的所有包(含自己)
    3. com.example.demo.*.service... demo包下任意包,但再下一层是service, service目录任意包
    1. *Controller 以Controller结尾
    2. User* 以User开头
      • 任意
  3. 方法名,不能省略
    1. add* 以add开头
    2. *xxx 以xxx结尾
      • 任意
  4. 参数
    1. () 无参
    2. (int) 一个整形
    3. (...) 参数任意
  5. +通配符,必须放在类后面,表示继承该类的所有子类包括自己
定义通知
java 复制代码
public class UserAop {
    /*
    定义切点,配置主动拦截规则
     */
    @Pointcut("execution(* com.example.demo.controller.UserController.*(..))")
    public void pointcut() {
    }
    /*
    前置通知
     */
    @Before("pointcut()")
    public void beforeAdvice() {
        System.out.println("执行了前置通知");
    }
    /*
    后置通知
     */
    @After("pointcut()")
    public void afterAdvice() {
        System.out.println("执行了后置通知");
    }

    /**
     * 环绕通知
     * @param ProceedingJoinPoint 规定写法
     * @return 返回Object给框架
     */
    @Around("pointcut()")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("进入环绕通知");
        Object obj = null;
        //执行目标方法
        obj = joinPoint.proceed();
        System.out.println("退出环绕通知");
        return obj;
    }
}

Spring AOP实现原理

Spring AOP是基于动态代理实现的,因此Spring对AOP的支持局限于方法级别的拦截。

动态代理:如上图所示,调用者不能直接发送请求给目标对象,而是先发送给代理类,代理类在给你转发到目标对象。

代理的生成时期:织入

Spring AOP的代理生成时期是"运行期",动态的织入字节码

Spring框架中的AOP实现方式有两种1.JDK proxy方式;2.CGLIB方式。在Spirng中默认是JDK方式,而在Spring boot中是CGLIB。

JDK实现要求被代理类必须实现接口,而CGLIB没有这个要求,是通过继承被代理类,所以被final修饰的代理类,无法被继承,只能选择JDK.

相关推荐
ChinaRainbowSea11 分钟前
十三,Spring Boot 中注入 Servlet,Filter,Listener
java·spring boot·spring·servlet·web
小游鱼KF14 分钟前
Spring学习前置知识
java·学习·spring
阿乾之铭2 小时前
spring MVC 拦截器
java·spring·mvc
小电玩2 小时前
谈谈你对Spring的理解
java·数据库·spring
徐*红4 小时前
springboot使用minio(8.5.11)
java·spring boot·spring
哈喽,树先生6 小时前
1.Seata 1.5.2 seata-server搭建
spring·springcloud
小菜yh9 小时前
关于Redis
java·数据库·spring boot·redis·spring·缓存
爱上语文11 小时前
Springboot的三层架构
java·开发语言·spring boot·后端·spring
荆州克莱11 小时前
springcloud整合nacos、sentinal、springcloud-gateway,springboot security、oauth2总结
spring boot·spring·spring cloud·css3·技术