当前位置: 首页 > news >正文

Spring AOP统一功能处理

在这里插入图片描述

⭐️前言⭐️

这篇文章主要介绍AOP(Aspect Oriented Programming)——面向切面编程的思想,它是对某一类事情的集中处理,也是对OOP(Object Oriented Programming)面向对象编程的补充和完善。

🍉欢迎点赞 👍 收藏留言评论 📝私信必回哟😁

🍉博主将持续更新学习记录收获,友友们有任何问题可以在评论区留言

🍉博客中涉及源码及博主日常练习代码均已上传GitHub


请添加图片描述

📍内容导读📍

  • 🍅1.面向切面编程AOP
    • 1.1 什么是AOP?
    • 1.2 AOP的作用
    • 1.3 AOP基础组成
  • 🍅2.Spring AOP 实现
    • 2.1添加 Spring AOP 框架支持
    • 2.2定义切面和切点
      • 切点表达式说明
    • 2.3定义通知
  • 🍅3.Spring AOP 实现原理
  • 🍅4.总结

🍅1.面向切面编程AOP

1.1 什么是AOP?

AOP(Aspect Oriented Programming):面向切面编程,它是一种思想,它是对某一类事情的集中处理。比如用户登录权限的效验,没学AOP之前,我们所有需要判断用户登录的页面(中的方法),都要各自实现或调用用户验证的方法,然而有了AOP之后,我们只需要在某一处配置一下,所有需要判断用户登录页面(中的方法)就全部可以实现用户登录验证了,不再需要每个方法中都写相同的用户登录验证了。

AOP是一种思想,而Spring AOP这个框架是对AOP思想的实现,它们的关系和IoC和DI类似。

1.2 AOP的作用

想象一个场景,我们在做后台系统时,除了登录和注册等几个功能不需要做用户登录验证之外,其他几乎所有页面调用的前端控制器(Controller)都需要先验证用户登录的状态,那么这个时候我们要怎么处理呢?

如果不使用AOP,我们之前的处理方式是每个Controller都要写一遍用户登录验证,然而当你的功能越来越多,那么你要写的登录验证也越来越多,就有了很多重复的代码,而且这些方法的代码修改和维护的成本就会很高。

如果使用AOP,在进入业务代码之前进行统一的一个处理,去验证用户是否登录。

除了统一的用户登录判断之外,AOP还可以实现:

  • 统一日志记录
  • 统一方法执行时间统计
  • 统一的返回格式设置
  • 统一的异常处理
  • 事务的开启和提交

也就是说使用AOP可以扩充多个对象的某个能力,所以AOP可以说是OOP(Object Oriented Programming)面向对象编程的补充和完善。

1.3 AOP基础组成

AOP由以下四部分组成

  • 1.切面(Aspect):定义AOP业务类型(表示当前AOP是做什么的)。
  • 2.连接点(Join Point):有可能调用AOP的地方就叫做一个连接点。
  • 3.切点(Pointcut):定义AOP拦截规则。
  • 4.通知(Advice)【增强方法】:定义什么时候干什么事。
    a) 前置通知:在拦截的目标方法之前执行的通知(事件)
    b)后置通知:在拦截的目标方法之后执行的通知(事件)
    c)返回之后通知:在拦截的目标方法返回数据之后通知
    d)抛出异常之后的通知:在拦截的目标方法抛出异常之后执行的通知
    e)环绕通知:在拦截方法执行前后都执行的通知。

AOP整个组成部分的概念如下图所示,以多个页面都要访问用户登录权限为例:
在这里插入图片描述

🍅2.Spring AOP 实现

我们接下来使用Spring AOP来实现AOP的功能,完成的目标是拦截所有UserController里面的方法,每次调用UserController中任意一个方法时,都执行相应的通知事件。

Spring AOP的具体实现步骤如下:

2.1添加 Spring AOP 框架支持

pom.xml中添加如下配置:

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.2定义切面和切点

切点指的是具体要处理的某一类问题,比如用户登录权限验证就是一个具体的问题,记录所有方法的执行日志就是一个具体的问题,切点定义的是某一类问题。

具体实现如下:
在这里插入图片描述
其中pointcut方法为空方法,其不需要方法体,此方法名就是起到一个“标识”的作用,标识下面的通知方法具体指的是哪个切点。

切点表达式说明

AspectJ支持三种通配符
*:匹配任意字符,只匹配一个元素(包,类,或方法,方法参数)
..:匹配任意字符,可以匹配多个元素,在表示类时,必须和*联合使用
+:表示按照类型匹配指定类的所有类,必须跟在类名后面,如com.cad.Car+,表示继承该类的所有子类包括本身

表达式示例如下:

  • execution(* com.example.demo.UserController. *(..)):匹配UserController类里的所有方法。
  • execution(* com.example.demo.UserController+.*(..)):匹配UserController类的子类包括该类的所有方法
  • execution(* com.example.demo.*.*(..)):匹配com.example.demo包下的所有类的所有方法
  • execution(* com.example.demo..*.*(..)):匹配com.example.demo包下、子孙包下所有类的所有方法
  • execution(* addUser(String,int)):匹配addUser方法,且第一个参数类型是String,第二个参数类型是int

2.3定义通知

通知定义的是被拦截的方法具体要执行的业务,比如用户登录权限验证方法就是具体要执行的业务。
Spring AOP中,可以在方法上使用以下注解,会设置方法为通知方法,在满足条件后会通知本方法进行调用:
a) 前置通知使用@Before:在拦截的目标方法之前执行的通知(事件)
b)后置通知使用@After:在拦截的目标方法之后执行的通知(事件)
c)返回之后通知使用@AfterReturning:在拦截的目标方法返回数据之后通知
d)抛出异常之后的通知使用@AfterThrowing:在拦截的目标方法抛出异常之后执行的通知
e)环绕通知使用@Around:在拦截方法执行前后都执行的通知。

具体实现如下:

@Component
@Aspect  // 标识当前类为一个切面
public class LoginAop {
    // 定义切点(拦截的规则),使用AspectJ表达式语法
    @Pointcut("execution(* com.example.demo.controller.UserController.*(..))")
    public void pointcut() {
    }
    
    // 前置通知
    @Before("pointcut()")
    public void doBefore() {
        System.out.println("执行了前置通知");
    }
    
    // 后置通知
    @After("pointcut()")
    public void doAfter() {
        System.out.println("执行了后置通知");
    }
    
    // 环绕通知
    @Around("pointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint) {
        Object result=null;
        // 前置业务代码
        System.out.println("环绕通知的前置执行方法");
        try {
            // 执行目标方法
            result=joinPoint.proceed();
        }catch (Throwable e) {
            e.printStackTrace();
        }
        // 后置业务执行代码
        System.out.println("环绕通知的后置执行代码");
        return result;
    }
}

访问UserController类中方法对应的URL,控制台打印结果如下图:
在这里插入图片描述

🍅3.Spring AOP 实现原理

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

Spring AOP支持 JDK Proxy 和 CGLIB 方式实现动态代理。默认情况下,实现了接口的类,使用AOP会基于JDK生成代理类,没有实现接口的类,会基于 CGLIB 生成代理类。
在这里插入图片描述
Spring AOP本质就是生成了一个目标对象的代理类,当前端传来请求时,不会将请求直接交给目标对象,而是首先由代理类进行处理,如果满足一定的条件,才会将请求交给目标对象。

比如:如果处理请求前需要登录验证,那么代理类会去验证用户是否登录,如果用户登录了才会将请求交给目标对象并执行核心业务代码,否则代理类将返回响应让用户先登录。

🍅4.总结

AOP是对某方面能力的统一实现,它是一种实现思想,Spring AOP是对AOP的具体实现,Spring AOP可通过AspectJ(注解)的方式来实现AOP的功能,Spring AOP的实现步骤是:

1.添加AOP框架支持
2.定义切面和切点
3.定义通知

Spring AOP是通过动态代理的方式,在运行期将AOP代码织入到程序中的,它的实现方式有两种:JDK Proxy和CGLIB。


⭐️最后的话⭐️
总结不易,希望uu们不要吝啬你们的👍哟(^U^)ノ~YO!!如有问题,欢迎评论区批评指正😁

请添加图片描述

相关文章:

  • 《Django框架从入门到实战》目录
  • 【华为机试真题详解】信号强度【2022 Q4 | 200分】
  • 【Linux】顶级编辑器Vim的基本使用及配置
  • Servlet 综合案例(empProject)
  • JVM 如何获取当前容器的资源限制?
  • linux之vim编辑器
  • 扩展欧几里得算法 - exgcd
  • 安卓移动端调用自然语言处理nlp模型【示例+源码】
  • 智能车|ROS主控与STM32建立通信软硬件全方位讲解
  • 【MySQL】MySQL基本数据类型
  • 【Docker】(二)使用Dockerfile构建并发布一个SpringBoot服务
  • 前端bug每次都比后端多,我总结了5点原因
  • linux下常用调试技巧
  • JSON数据解析
  • 性能优化系列之如何正确理解和实现前后端分离?
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • 03Go 类型总结
  • Android开发 - 掌握ConstraintLayout(四)创建基本约束
  • leetcode388. Longest Absolute File Path
  • macOS 中 shell 创建文件夹及文件并 VS Code 打开
  • RedisSerializer之JdkSerializationRedisSerializer分析
  • 阿里云应用高可用服务公测发布
  • 阿里中间件开源组件:Sentinel 0.2.0正式发布
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 从0搭建SpringBoot的HelloWorld -- Java版本
  • 分布式事物理论与实践
  • 分类模型——Logistics Regression
  • 开放才能进步!Angular和Wijmo一起走过的日子
  • 目录与文件属性:编写ls
  • 项目实战-Api的解决方案
  • 《码出高效》学习笔记与书中错误记录
  • 摩拜创始人胡玮炜也彻底离开了,共享单车行业还有未来吗? ...
  • # include “ “ 和 # include < >两者的区别
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • (C#)if (this == null)?你在逗我,this 怎么可能为 null!用 IL 编译和反编译看穿一切
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第5节(封闭类和Final方法)
  • (Pytorch框架)神经网络输出维度调试,做出我们自己的网络来!!(详细教程~)
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (六)vue-router+UI组件库
  • (七)理解angular中的module和injector,即依赖注入
  • (一)Neo4j下载安装以及初次使用
  • (转)一些感悟
  • .NET 2.0中新增的一些TryGet,TryParse等方法
  • .NET CLR基本术语
  • .Net 转战 Android 4.4 日常笔记(4)--按钮事件和国际化
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)...
  • .net流程开发平台的一些难点(1)
  • [AndroidStudio]_[初级]_[修改虚拟设备镜像文件的存放位置]
  • [AR Foundation] 人脸检测的流程
  • [C++]命名空间等——喵喵要吃C嘎嘎
  • [CareerCup] 2.1 Remove Duplicates from Unsorted List 移除无序链表中的重复项
  • [ChromeApp]指南!让你的谷歌浏览器好用十倍!
  • [Codeforces] combinatorics (R1600) Part.2
  • [codeforces]Checkpoints