• SpringAOP详解


    目录

    前言:

    相关概念

    切点表达式规则

    代码演示

    SpringAOP实现原理

    织入(代理的生成时机)

    JDK和CGLIB区别

    小结:


    前言:

        AOP(Aspect Oriented Programming)是思想(面向切面编程),对某一类事情的统一处理。Spring AOP是思想的具体实现框架。

    相关概念

    1)切面(类)
        某一方面的具体内容处理就是一个切面。比如用户登录判断就是一个切面(接口对于登录权限的校验)。
    2)切点(方法)
        定义拦截规则。比如切面对于哪些接口都需要进行判断。
    3)通知(方法的具体实现)
        执行AOP业务(具体需要执行的拦截方法)

    • 前置通知:在目标方法(实际要执行的方法)调用之前执行的通知。
    • 后置通知:在目标方法执行之后的通知。
    • 环绕通知:在目标方法执行前,后都执行的通知。
    • 异常通知:在目标方法抛异常执行的通知。
    • 返回通知:在目标方法返回执行的通知。

    4)连接点
        所有可能触发切点的点就是连接点(被这个切面所处理的点)。

    切点表达式规则

        切点表达式由切点函数组成,其中execution()是最常用的切点函数,用来匹配方法。

    语法:

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

        修饰符和异常可以省略(一般异常都是省略)

    示例:

        execution(* com.example.demo.controller.UserController.*(..))

        匹配UserController类下的任意方法,参数任意。返回值任意。

    注意:

        这种表达式的书写是非常繁琐的,目前有更好的AOP实现,可以更加灵活的配置。

    代码演示

    设置切面

    1. package com.example.demo.common;
    2. import org.aspectj.lang.ProceedingJoinPoint;
    3. import org.aspectj.lang.annotation.*;
    4. import org.springframework.stereotype.Component;
    5. import java.time.LocalDateTime;
    6. @Aspect // 切面
    7. @Component // 添加到框架中
    8. public class UserAOP {
    9. // 切点(配置拦截规则)
    10. // 返回值(任意) 具体类(UserController) 方法名(任意) 参数(任意)
    11. @Pointcut("execution(* com.example.demo.controller.UserController.*(..))")
    12. public void pointcut(){
    13. }
    14. // 前置通知
    15. @Before("pointcut()")
    16. public void doBefore() {
    17. System.out.println("执行了前置通知:" + LocalDateTime.now());
    18. }
    19. // 后置通知
    20. @After("pointcut()")
    21. public void doAfter() {
    22. System.out.println("执行了后置通知:" + LocalDateTime.now());
    23. }
    24. // 环绕通知
    25. @Around("pointcut()")
    26. public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
    27. System.out.println("开始执行环绕通知");
    28. // 执行连接点中的方法(基点)
    29. Object obj = joinPoint.proceed();
    30. System.out.println("结束执行环绕通知");
    31. return obj;
    32. }
    33. }

    定义连接点

    1. package com.example.demo.controller;
    2. import org.springframework.web.bind.annotation.RequestMapping;
    3. import org.springframework.web.bind.annotation.RestController;
    4. @RestController
    5. public class UserController {
    6. @RequestMapping("/user/hello")
    7. public String hello() {
    8. System.out.println("执行了hello方法");
    9. return "hello";
    10. }
    11. @RequestMapping("/user/login")
    12. public String login() {
    13. System.out.println("执行了login方法");
    14. return "login";
    15. }
    16. }

        当访问/user/hello这个接口,控制台的打印。

    注意:

        可以清楚的看到执行目标方法时,前置通知、后置通知和环绕通知的执行时机。

    SpringAOP实现原理

        Spring AOP 是构建在动态代理基础上,因此 Spring 对 AOP 的支持局限于方法级别的拦截(使用动态代理技术实现方法的调用)。

        Spring AOP 支持 JDK Proxy CGLIB 方式实现动态代理。默认情况下,实现了接口的类,使用 SpringAOP 会基于 JDK 生成代理类,没有实现接口的类,会基于 CGLIB 生成代理类。

    织入(代理的生成时机)

        织入是把切面应用到目标对象并创建新的代理对象的过程,切面在指定的连接点被织入到目标对
    象中。
    在目标对象的生命周期里有多个点可以进行织入:

    1)编译期

        切面在目标类编译时被织入。这种方式需要特殊的编译器。AspectJ的织入编译器就
    是以这种方式织入切面的。

    2)类加载期

        切面在目标类加载到JVM时被织入。这种方式需要特殊的类加载器(ClassLoader),它可以在目标类被引入应用之前增强该目标类的字节码。AspectJ5的加载时织入(load-time weaving. LTW)就支持以这种方式织入切面。

    3)运行期

        切面在应用运行的某⼀时刻被织入。⼀般情况下,在织入切面时,AOP容器会为目标对象动态创建⼀个代理对象。SpringAOP就是以这种方式织入切面的。

    JDK和CGLIB区别

        1)JDK 实现(反射方式),要求被代理类必须实现接口,之后是通过 InvocationHandler 及 Proxy,在运行时动态的在内存中生成了代理类对象,该代理对象是通过实现同样的接口实现(类似静态代理接口实现的方式),只是该代理类是在运行期时,动态的织入统一的业务逻辑字节码来完成。可以代理任意类。性能相对较高,生成代理对象速度较快。

        2)CGLIB 实现(字节码加强技术),被代理类可以不实现接口,是通过继承被代理类(生成目标对象的子类),在运行时动态的生成代理类对象(字节码加强技术)。无法代理 final 类和 final 方法。性能相对较低,生成代理对象速度较慢。

    注意:

        在 Spring 框架中,即使用了 JDK 动态代理又使用 CGLIB,默认情况下使用的是 JDK 动态代理,但是如果目标对象没有实现接口,则会使用 CGLIB 动态代理。

    小结:

        面向切面编程就是统一功能的处理,SpringAOP实现了这种技术。通过动态代理的方式:JDK动态代理通过反射的方式实现,速度快,要求被代理类必须实现接⼝。CGLIB通过实现代理类的子类实现动态代理(字节码加强技术),代理类不能是final修饰。

  • 相关阅读:
    【面试题】 TypeScript 前端面试题 由浅到深
    高质量数据is all you need:Textbooks Are All You Need论文笔记
    算法基础1.1 快速排序
    基于单片机压力传感器MPX4115检测-报警系统-proteus仿真-源程序
    redis(普通连接和连接池、字符串类型、hash类型、列表类型)
    [计算机网络]IP协议
    第二次pta认证P测试C++
    PCDViewer的常用操作
    Linux | 性能问题排查
    2022-2028年全球与中国便携式茶包市场现状及未来发展趋势分析报告
  • 原文地址:https://blog.csdn.net/weixin_62353436/article/details/131144080