【JavaEE】面向切面编程AOP是什么-Spring AOP框架的基本使用

news2024/10/1 19:21:57

【JavaEE】Spring AOP(1)

在这里插入图片描述

文章目录

  • 【JavaEE】Spring AOP(1)
    • 1. Spring AOP 是什么
      • 1.1 AOP 与 Spring AOP
      • 1.2 没有AOP的世界是怎样的
      • 1.3 AOP是什么
    • 2. Spring AOP 框架的学习
      • 2.1 AOP的组成
        • 2.1.1 Aspect 切面
        • 2.1.2 Pointcut 切点
        • 2.1.3 Advice 通知
        • 2.1.4 Join Point 连接点
      • 2.2 Spring AOP的基本使用
        • 2.2.1 引入依赖
        • 2.2.2 定义一个Aspect
        • 2.2.3 定义一个Pointcut
        • 2.2.4 Join Point
        • 2.2.5 定义Advice
          • 2.2.5.1 前置通知,后置通知与返回通知
          • 2.2.5.2 异常通知
          • 2.2.5.3 环绕通知
      • 2.3 Spring AOP的实现原理
        • 2.3.1 动态代理
        • 2.3.2 Spring AOP动态代理组成
        • 2.3.3 JDK Proxy 与 CGLIB的区别

【JavaEE】Spring AOP(1)

1. Spring AOP 是什么

1.1 AOP 与 Spring AOP

AOP (**A**spect **O**riented Programming),是一种思想,即面向切面编程

Spring AOP 则是一个框架,Spring项目中需要引入依赖而使用

  • AOP和Spring AOP的关系就相当于IoC和DI
  • Spring AOP让开发者能够半自动的开发AOP思想下实现的功能

1.2 没有AOP的世界是怎样的

我们要实现用户登录校验的功能,没有实现AOP之前,我们只能这样做:

博客系统登录功能实现,博客传送门:【JavaEE】前后端综合项目-博客系统(下)_s:103的博客-CSDN博客

  1. 前端进入每一个页面的时候,专门发送“登录校验”的请求给后端进行登录校验
  2. 前端发送每一个请求的时候,后端都会自动进行登录校验

无论是哪种,都有这样的特性,就是代码耦合度高,网页的每个功能都要各自实现“登录校验”的代码,这样的坏处是:

  1. 不符合专一设计原则,开发者开发一个功能就应该全心全意,有针对性,这样开发效率也会高点儿~
  2. 耦合度很高,一改则需万改

图示:

在这里插入图片描述

1.3 AOP是什么

刚才说了,AOP是面向切面编程,这是英语直译的结果,不用太多理会~

  • 可以理解为,它是 对某一类事情的集中处理

有了AOP后,我们只需要在代码的某一处配置一下,所有的功能就能实现用户登录校验了,不再需要重复写那些代码了~

  • 也对“登录校验”这个步骤,集中处理了,这个代码开发过程就是面向切面编程

切面可以理解为,切下来的一个方面,一个步骤

切下来后有种藕断丝连的感觉:

藕断丝连 的图像结果

在这里插入图片描述

例如这个图,再等一下讲解AOP的组成之后,回头看可能会有更好的理解~

  • AOP后,功能表现还是左上,但是代码长成右下
  • “登录校验”被切了下来一样

如果把切面看成动作执行者,✂

  • 我们可以将切面形象地比喻为一把剪刀。
  • 剪刀可以在不改变原始材料的情况下,将其切割成不同的形状
  • 同样,切面在编程中也可以在不修改原始代码的情况下,将横切关注点应用到不同的对象或方法上
    • 在代码实现的时候,将需要的统一处理的功能,“剪”下来进行统一处理
  • 就像剪刀可以将材料切割成不同的形状一样,切面可以将横切关注点切割并应用到代码的不同部分,从而实现代码的模块化和重用

例如,调用功能1的时候,会通过切下来的“面”的匹配对应的“块”,之后进行“组装”~

  • 这样就在调用功能1之前进行了登录校验

好处:

  1. 满足单一设计原则,登录校验的存在,不会改变各个功能的原代码
  2. 耦合度低,改一处等于改一万处

AOP就很适合解决这种功能统一,且是使用的地方较多的功能了

  • AOP的统一处理!

除了登录校验外,还可以实现:

  • 统一
    1. 日志记录
    2. 方法执行时间统计
    3. 返回格式设置
    4. 异常处理
    5. 事务开启与提交
    6. 等等…

也可以说,AOP面向了多个对象

也就是说,AOP是OOP(Object Oriented Programming,面向对象编程)的一个补充和完善

2. Spring AOP 框架的学习

Spring AOP框架内部实现了AOP,开发者按照规则写下的代码,就对应着AOP逻辑

Spring AOP的学习分为以下三步:

  1. AOP的组成
  2. Spring AOP的基本使用
  3. Spring AOP的实现原理

2.1 AOP的组成

2.1.1 Aspect 切面

一个Aspect代表一个“统一处理”,因为统一设计原则,一个切面就是一个功能,例如“登录校验”

  • 包含切点、通知,即有横切逻辑的定义,也有连接点的定义

如果把这些定义,看成“切面”的独一无二的横切面,看成标识,切面就对应那个“块”,也就是功能,所以切面就看成一个功能~

即,AOP是干啥的

2.1.2 Pointcut 切点

规定 这个切面是从哪些,前后端交互接口,“剪”下来的

  • 例如:定义用户登录拦截规则,哪些接口才需要判断用户登录权限

2.1.3 Advice 通知

AOP执行的具体方法

  • 例如:获取用户信息,如果后端有记录对应的登录信息,就说明已经登录,否则没有登录

2.1.4 Join Point 连接点

有可能触发切点的所有点

  • 满足切点规则的所有前后端交互接口

2.2 Spring AOP的基本使用

通过代码实现,你可能会有更切合的体验!

  • 我只讲一种方式,其他感兴趣的可以去学,有需要的去学

2.2.1 引入依赖

你会发现,在IDEA的勾选选入依赖里,没有AOP这个选项,这也很正常,因为并不是所有依赖都包含在其中!

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

在这里插入图片描述

  • 第一次加载会有点慢,注意网络通畅~

2.2.2 定义一个Aspect

在这里插入图片描述

一个切面其实就是一个类,加上@Aspect注解,这个类就是为了实现某个“统一处理”的

  • 需要加五大类注解,这个算是个组键吧,所以用@Component

2.2.3 定义一个Pointcut

在这里插入图片描述

一个方法加上注解@Pointcut,在括号内写一些语句,就定义了一个切点

  • 这个方法可以不返回一切,方法名自定义,没有参数列表,没有代码体…,如果加了会怎么样感兴趣可以去了解,但是暂时用不到~
  • 括号内部的语句是有对应的语法的,这里了解这句话的含义,举一反三就好,语法是啥感兴趣可以去了解

execution(* com.example.demo.controller.TestController.*(..)),解析:

  1. execution(),执行括号中提及的方法,就触发切点
  2. *,不限制方法权限(public、private…),全部方法
  3. com.example.demo.controller.TestController.,针对的类的位置
  4. *(..),代表类中的所有方法
    1. *,所有的方法名
    2. (..),任意的参数列表

2.2.4 Join Point

对于连接点,则是刚才切点对应的前后端交互接口:

  1. /test/say_hi
  2. /test/say_hello

我们在这里不需要在意其他业务,只需要专注开发,而Aspect的代码开发里则面向了这几个连接点!

在这里插入图片描述

为了与通知的方法区分,我在控制台打印信息:

在这里插入图片描述

2.2.5 定义Advice

通知就是访问对应接口的时候,要执行的业务,分为五种通知:

  1. 前置通知
  2. 后置通知
  3. 环绕通知
  4. 返回通知
  5. 异常通知

顾名思义,区分就是,通知执行的时机~

对应五种注解(加在一个方法的上面,此方法被称为通知方法):

  1. @Before,通知方法在目标方法执行之前执行
  2. @After,通知方法在目标方法执行之后执行
  3. @Around,通知包裹了目标方法,自定义行为
  4. @AfterReturning,通知方法在目标方法返回后调用
  5. @AfterThrowing,通知方法在目标抛出异常后调用
2.2.5.1 前置通知,后置通知与返回通知
// 前置通知
@Before("pointcut()")
public void doBefore(){
    System.out.println("执⾏ Before ⽅法");
}
// 后置通知
@After("pointcut()")
public void doAfter(){
    System.out.println("执⾏ After ⽅法");
}
// return 之前通知
@AfterReturning("pointcut()")
public void doAfterReturning(){
    System.out.println("执⾏ AfterReturning ⽅法");
}

注解括号内代表,对应的切点方法

效果:

在这里插入图片描述

按多次:

在这里插入图片描述

2.2.5.2 异常通知
// 抛出异常之前通知
@AfterThrowing("pointcut()")
public void doAfterThrowing(){
    System.out.println("执⾏ doAfterThrowing ⽅法");
}

对于异常通知的触发案例,项目开发很少用,暂时不介绍

2.2.5.3 环绕通知

自定义行为的通知,可以模拟其他通知~

@Around("pointcut()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
    Object object = null;
    System.out.println("Around方法开始执行");
    object = joinPoint.proceed();
    System.out.println("Around方法结束执行");
    return object;
}

ProceedingJoinPoint这个类的对象joinPoint,代表着连接点对象

  • 调用proceed()方法代表进行这个连接点对于的方法
    • try catch后能模拟异常通知

记得返回这个object,不然框架处理不了返回值作为响应!

  • 默认执行后的返回值是交给框架的,而这里是交给object~

效果:

在这里插入图片描述

这样也看出了优先级~

环绕通知,更灵活

  • 更好的实现“原子性”,通过加锁就行,如执行时间统计…

  • 如后置通知方法需要跟前置通知方法有“数据交互”

2.3 Spring AOP的实现原理

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

2.3.1 动态代理

原本访问目标对象:

在这里插入图片描述

AOP之后:

在这里插入图片描述

就像fiddler一样,代理了请求,期间保留了其信息…

通过代理类,目标对象Join Point何时执行目标方法,代理说了算

  • 在环绕通知的时候体现尤为显著
  • 代理类 根据 Aspect 进行对应的行为

我们不通过Spring AOP框架,我们只能自己实现AOP才能实现在目标方法调用之前和调用之后…时机进行一些业务!

2.3.2 Spring AOP动态代理组成

  1. JDK Proxy
    • 代理类必须实现某个接口,才能使用JDK Proxy
    • 底层有用到反射…
  2. CGLIB
    • 通过实现代理类的子类来实现动态代理,只能代理能被继承的类

通过这两种动态代理的实现~

  • 单独一种有局限性

2.3.3 JDK Proxy 与 CGLIB的区别

  1. 出身不同
    • JDK Proxy 来自java
    • CGLIB 来自第三方
  2. 实现不同
    • JDK Proxy,通过代理类必须实现某个接口
    • CGLIB,通过实现代理类的子类
  3. 性能不同
    • jdk 7/7+,JDK Proxy性能略高于CBLIB
    • jdk7-,CBLIB性能远高于JDK Proxy

文章到此结束!谢谢观看
可以叫我 小马,我可能写的不好或者有错误,但是一起加油鸭🦆

不得不提的是,切面、切点、连接点、通知,这些名词,不要纠结他们为啥这么叫,咱们知道他们的含义,知道Spring AOP怎么开发就行了~

代码:spring_aop-demo · 游离态/马拉圈2023年8月 - 码云 - 开源中国 (gitee.com)


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/905230.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微人事 部门管理 模块 (十五)

部门管理的树展示和搜索 数据展示页是个树&#xff0c;我们一次性把数据加载出来也可以通过点一次id加载查询出来出来子部门&#xff0c;我们用一次拿到说有json数据加载出来 数据不多可以用递归&#xff0c;数据很多就用懒加载的方式 由于子部门比较深就不适合&#xff0c;权…

# 59. python的类与对象-更新

[目录] 文章目录 59. python的类与对象-更新1.面向对象编程2.什么是类3.什么是对象4.如何描述对象5.对象的属性和方法6.Python中的类7.type()函数查看数据类型8.类在Python中的应用9.总结 【正文】 59. python的类与对象-更新 1.面向对象编程 本节内容特别抽象&#xff0c;初…

Web3和去中心化:互联网的下一个演化阶段

文章目录 Web3和去中心化的定义Web3&#xff1a;去中心化&#xff1a; 为什么Web3和去中心化如此重要&#xff1f;数据隐私和安全&#xff1a;去中心化的创新&#xff1a;去除中间商&#xff1a; Web3和去中心化的应用领域去中心化金融&#xff08;DeFi&#xff09;&#xff1a…

wustojc2003求整数均值

#include <stdio.h> int main() {int a,b,c,d;double A;scanf("%d%d%d%d",&a,&b,&c,&d);A(double)((abcd)/4.0);//强转成doubleprintf("Sum %d\n",abcd);printf("Average %.2lf",A);return 0;}

C++笔记之基类指针动态地指向某一个子类情况列举

C笔记之基类指针动态地指向某一个子类情况列举 code review! 文章目录 C笔记之基类指针动态地指向某一个子类情况列举1.基本的多态示例2.基类中的成员函数可以设置为纯虚函数3.将基本示例修改为使用智能指针并在堆上实例化子类4.父类指针指向基类后&#xff0c;可以去调用只有…

【JUC系列-01】深入理解JMM内存模型的底层实现原理

一&#xff0c;深入理解JMM内存模型 1&#xff0c;什么是可见性 在谈jmm的内存模型之前&#xff0c;先了解一下并发并发编程的三大特性&#xff0c;分别是&#xff1a;可见性&#xff0c;原子性&#xff0c;有序性。可见性指的就是当一个线程修改某个变量的值之后&#xff0c…

shell脚本之sed

sed sed 即 Stream EDitor&#xff0c;和 vi 不同&#xff0c;sed是行编辑器 基本用法 sed [选项] 自身脚本用法 [支持输入标准输入管道] 常用选项&#xff1a;-n 不输出模式空间内容到屏幕&#xff0c;即不自动打印-e 多点编辑-f FILE 从指定文件中读取编辑脚本-r, -E 使用…

【TypeScript】内置对象

JavaScript 中很多内置对象&#xff0c;可以直接在 TypeScript 中当做定义好了的类型。 ECMAScript 的内置对象 Boolean、Number、String、RegExp、Date、Error、XMLHttpRequest 等 let num: Number new Number(1) let date: Date new Date() let reg: RegExp new RegExp(…

WTF Langchain极简入门: 03. 数据连接

加载文档 langchain提供多种文档加载器&#xff0c;支持多种格式、来源的文件。可以从本地存储系统加载文件&#xff0c;也可以从网上加载远端文件。想了解LangChain所支持的所有文档加载器&#xff0c;请参考Document Loaders。 在本系列课程中&#xff0c;我们将使用最基本…

Docker 搭建 LNMP + Wordpress(详细步骤)

目录 一、项目模拟 1. 项目环境 2. 服务器环境 3.任务需求 二、Linux 系统基础镜像 三、Nginx 1. 建立工作目录 2. 编写 Dockerfile 脚本 3. 准备 nginx.conf 配置文件 4. 生成镜像 5. 创建自定义网络 6. 启动镜像容器 7. 验证 nginx 四、Mysql 1.…

快速学习GO语言总结

备注&#xff1a;本博客将自己初步学习GO的总结进行分享&#xff0c;希望大家通过本博客可以在短时间内快速掌握GO的基本程序编码能力&#xff0c;如有错误请留言指正&#xff0c;谢谢&#xff01; 一、初步了解Go语言 &#xff08;一&#xff09;Go语言诞生的主要问题和目标…

shell脚本——expect脚本免交互

目录 一.Here Document 1.1.定义 1.2.多行重定向 二.expect实现免交互 2.1.基础免交互改密码 2.2.expect定义 2.3.expect基本命令 2.4.expect实现免交互ssh主机 一.Here Document 1.1.定义 使用I/O重定向的方式将命令列表提供给交互式程序&#xff0c;是标准输 入的一…

uniapp开发小程序,上传图片和视频功能

1.需求&#xff1a; 可以上传图片和视频&#xff0c;并且都可以删除&#xff0c;图片可以预览。 2.效果图 3.代码&#xff1a; <template><!-- 上传start --><view style"display: flex; flex-wrap: wrap;"><view class"update-file&quo…

FPGA解析串口指令控制spi flash完成连续写、读、擦除数据

前言 最近在收拾抽屉时找到一个某宝的spi flash模块&#xff0c;如下图所示&#xff0c;我就想用能不能串口来读写flash&#xff0c;大致过程就是&#xff0c;串口向fpga发送一条指令&#xff0c;fpga解析出指令控制flah&#xff0c;这个指令协议目前就是&#xff1a; 55 AA …

达梦数据库表空间创建和管理

概述 本文将介绍在达梦数据库如何创建和管理表空间。 1.创建表空间 1.1表空间个数限制 理论上最多允许有65535个表空间&#xff0c;但用户允许创建的表空间 ID 取值范围为0~32767&#xff0c; 超过 32767 的只允许系统使用&#xff0c;ID 由系统自动分配&#xff0c;ID不能…

周易卦爻解读笔记——小过

第六十二卦小过 雷山小过 震上艮下 小过卦为母卦&#xff0c;象征小有过越。 小过卦是中孚卦的错卦&#xff0c;序卦传【有信者必行之&#xff0c;故受之以小过】 小过&#xff1a;亨&#xff0c;利贞&#xff0c;可小事&#xff0c;不可大事。飞鸟遗之音&#xff0c;不宜上宜…

NEO-6M GPS模块 +无线透传模块组成短距离数据空中传输

NEO-6M GPS模块 无线透传模块组成短距离数据空中传输 &#x1f4cc;相关篇《GY-NEO6MV2 GPS模块测试》 &#x1f33f;NEO-6M GPS模块 &#x1f33f;透传模块采用的是GC2400-TC017 ✨数据的一收一发&#xff0c;需要配合一个USB转TTL工具&#xff0c;在电脑端通过串口调试助…

7-5 螺旋方阵

分数 20 全屏浏览题目 切换布局 作者 C课程组 单位 浙江大学 所谓“螺旋方阵”&#xff0c;是指对任意给定的N&#xff0c;将1到NN的数字从左上角第1个格子开始&#xff0c;按顺时针螺旋方向顺序填入NN的方阵里。本题要求构造这样的螺旋方阵。 输入格式&#xff1a; 输入在…

第3步---MySQL的DDL和DML操作

第3步---MySQL的DDL和DML操作 1.DDL操作 Data Defination Language 数据定义语言。创建数据库和表的不涉及到数据的操作。 1.1DDL基本操作 1.1.1数据库相关操作 ddl&#xff1a;创建数据库&#xff0c;创建和修改表 对数据库常见的操作&#xff1a; 操作数据库 -- 展示数据…

Unity 之 Input类

文章目录 总述具体介绍 总述 Input 类是 Unity 中用于处理用户输入的重要工具&#xff0c;它允许您获取来自键盘、鼠标、触摸屏和控制器等设备的输入数据。通过 Input 类&#xff0c;您可以轻松地检测按键、鼠标点击、鼠标移动、触摸、控制器按钮等用户输入事件。以下是关于 I…