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

Spring之AOP思想

目录

什么是AOP

 ​​​为什么用AOP

Spring AOP 应该怎么学习呢

AOP下的一些核心概念(SpringAOP并没有实现所有的概念)

基于概念的使用Spring的AOP 

一个使用的实例

关于切点的匹配

通知的种类

 使用注解的方式来实现功能​编辑

AOP框架背后的核心 

需要实现两个原理

AOP的应用-事务场景

事务的概念 

事务的隔离性

 Spring的提供的一个事务切点@Transcctional​编辑


什么是AOP

  • AOP面对切面编程,它是一种思想,它是对某一类事情的集中处理。比如用户获奖权限的效验,没学 AOP 之前,我们所有需要判断用户获奖权限的页面(中的方法),都要各自实现或调用用户验证的方法,然而有了 AOP 之后,我们只需要在某一处配置一下,所有需要判断用户中将权限页面(中的方法)就全部可以实现用户用户中将权限验证了,不再需要每个方法中都写相同的用户登录验证了。而 AOP 是一种思想,而 Spring AOP 是一个框架,提供了一种对 AOP 思想的实现,它们的关系和 IoC与 DI 类似。
  • Spring下的AOP,Java AOP做的比较早的AspectJ库,是相当于做的比较早,Spring的AOP的在使用方式的时候,很多也延续了AspectJ的方式

 ​​​为什么用AOP

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

  • 我们之前的处理方式是每个 Controller 都要写一遍用户登录验证,然而当你的功能越来越多,那么你要写的登录验证也越来越多,而这些方法又是相同的,这么多的方法就会代码修改和维护的成本。那有没有简单的处理方案呢?答案是有的,对于这种功能统一,且使用的地方较多的功能,就可以考虑 AOP来统一处理了。

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

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

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


Spring AOP 应该怎么学习呢

  • 1. 学习 AOP 是如何组成的?也就是学习 AOP 组成的相关概念。

  • 2. 学习 Spring AOP 使用。

  • 3. 学习 Spring AOP 实现原理。
     

AOP下的一些核心概念(SpringAOP并没有实现所有的概念)

Aspect 切面

  • 逻辑概念,指的就是放置各种公共业务的,以及公共业务如何和具体的业务产生关系的配置的地方
  • 切面(Aspect)由切点(Pointcut)和通知(Advice)组成,它既包含了横切逻辑的定义,也包括了连接点的定义。

Join Point连接点

  • 切面和业务发生关系的地方,Spring AOP中仅支持方法的这一个连接点,所以在使用Spring AOP的时候,不太提这个概念

Advice通知

  • 方法执行之前还是之后或者是包围方法

Point CUT 切入点

  • 哪些方法被切入

 

 

基于概念的使用Spring的AOP 


Spring AOP 的实现步骤如下:

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

注入相应的依赖

一个使用的实例

 定义切面

 

关于切点的匹配

  • Aspectl是Java的AOP领域的领头羊,所以它的方案基本就称为Java AOP的标准存在了,所以AspectJ定义一组表达式的语法,来描述Pointcut,所以Spring AOP也使用这种表达式,Spring AOP和AspectJ(也是一种AOP框架)之间其实是没有关系的 
  • 就像我们很多聊天软件都采用了这种聊天框

AspectJ 支持三种通配符:

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

切点表达式由切点函数组成,其中 execution() 是最常用的切点函数,用来匹配方法,语法为:execution(<修饰符><返回类型><包.类.方法(参数)><异常>)修饰符和异常可以省略。

 

  •  匹配表达式是写在@Pointcut()里面的

 

通知的种类

  • 前置通知使用 @Before:通知方法会在目标方法调用之前执行
  • 后置通知使用 @After:通知方法会在目标方法返回或者抛出异常后调用。
  • 返回之后通知使用 @AfterReturning:通知方法会在目标方法返回后调用
  • 抛异常后通知使用 @AfterThrowing:通知方法会在目标方法抛出异常后调用。
  • 环绕通知使用 @Around:通知包裹了被通知的方法,在被通知的方法通知之前和调用之后执行自定义的行为。这个方法是很万能的,理论上有了Around可以实现上面四种

 

 使用注解的方式来实现功能

 

 

AOP框架背后的核心 

需要实现两个原理

对象代理

  • Spring AOP框架的核心原理,因此 Spring 对 AOP 的支持局限于方法级别的拦截
  • Spring AOP 支持 JDK Proxy 和 CGLIB 方式实现动态代理。现在Spring默认都是CGLJB方式

JDK Proxy vs CGLIB Proxy

  • JDK 实现,要求被代理类必须实现接口,之后是通过 InvocationHandler 及 Proxy,在运行时动态的在内存中生成了代理类对象,该代理对象是通过实现同样的接口实现(类似静态代理接口实现的方式),只是该代理类是在运行期时,动态的织入统一的业务逻辑字节码来完成。
  • CGLIB 实现,被代理类可以不实现接口,是通过继承被代理类,在运行时动态的生成代理类对象。
  • JDK Proxy只能针对接口做对象代理,而CGLib可以针对任意对象代理,所以它的适用场景更广
     

CGLib的实现代理

 

 

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

  • 编译期:切面在目标类编译时被织入。这种方式需要特殊的编译器。AspectJ的织入编译器就是以这种方式织入切面的。
  • 类加载器:切面在目标类加载到JVM时被织入。这种方式需要特殊的类加载器(ClassLoader),它可以在目标类被引入应用之前增强该目标类的字节码。AspectJ5的加载时织入(load-timeweaving. LTW)就支持以这种方式织入切面。
  • 运行期:切面在应用运行的某一时刻被织入。一般情况下,在织入切面时,AOP容器会为目标对象动态创建一个代理对象。SpringAOP就是以这种方式织入切面的

动态代理

  • 此种实现在设计模式上称为动态代理模式,在实现的技术手段上,都是在 class 代码运行期,动态的织入字节码。
  • 我们学习 Spring 框架中的AOP,主要基于两种方式:JDK 及 CGLIB 的方式。这两种方式的代理目标都是被代理类中的方法,在运行期,动态的织入字节码生成代理类。
  • CGLIB是Java中的动态代理框架,主要作用就是根据目标类和方法,动态生成代理类。
  • Java中的动态代理框架,几乎都是依赖字节码框架(如 ASM,Javassist 等)实现的。字节码框架是直接操作 class 字节码的框架。可以加载已有的class字节码文件信息,修改部分信息,或动态生成一个 class。

 简单实现

 

AOP的应用-事务场景

事务的概念 

  • 事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败。就是将这一组操作作为一个整体
  • 在不同的环境中,都可以有事务。对应在数据库中,就是数据库事务。

其实整体的概念就是保证一致性

  • 我们就引入显式事务这种概念 来告诉MySQ几条SQL语句是一个整体
  • 如果只是一条SQL吗,其实就是一个事务,称为隐式事务

 为了保证一致的四个特性

  •  Mysql的实现者在就保证了事务的四大特性
  • Mysql的使用者就要正确的Mysql提供事务原语

事务的隔离性

 

 Spring的提供的一个事务切点@Transcctional

 

 

 

相关文章:

  • TypeScript 小结
  • Netty(10)协议设计与解析(IdleStateHandler:空闲检测器、心跳)
  • PostgreSQL数据库统计信息——analyze大致流程
  • C开发环境与基础
  • Android系统_MSM8953_android10_adb连接adbd加入密码检测
  • 23设计模式之 --------- 什么是设计模式?
  • 在以「基础设施」为定位的发展阶段里,产业变成了一个可以有诸多创新的存在
  • Vue相关面试题(1)
  • 基于SpringBoot的网上购物商场管理系统
  • Python——time模块
  • 【深度学习】卷积神经网络的架构参考 以MNIST数据集为例(未调节架构)测试集正确率: 98.66%
  • C++ 哈希桶模拟实现(补充)
  • Rethinking the Inception Architecture for Computer Vision--Christian Szegedy
  • 安卓毕业设计成品基于Uniapp+SSM实现的智能课堂管理APP在线学习网
  • 基于metaRTC嵌入式webrtc的H265网页播放器实现(我与metaRTC的缘分)
  • $translatePartialLoader加载失败及解决方式
  • [ JavaScript ] 数据结构与算法 —— 链表
  • Codepen 每日精选(2018-3-25)
  • electron原来这么简单----打包你的react、VUE桌面应用程序
  • ES6系统学习----从Apollo Client看解构赋值
  • idea + plantuml 画流程图
  • Leetcode 27 Remove Element
  • Sublime text 3 3103 注册码
  • 阿里研究院入选中国企业智库系统影响力榜
  • 回流、重绘及其优化
  • 看域名解析域名安全对SEO的影响
  • 两列自适应布局方案整理
  • 你不可错过的前端面试题(一)
  • 软件开发学习的5大技巧,你知道吗?
  • 为物联网而生:高性能时间序列数据库HiTSDB商业化首发!
  • 主流的CSS水平和垂直居中技术大全
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • python最赚钱的4个方向,你最心动的是哪个?
  • 通过调用文摘列表API获取文摘
  • $.ajax,axios,fetch三种ajax请求的区别
  • ${factoryList }后面有空格不影响
  • (13)Latex:基于ΤΕΧ的自动排版系统——写论文必备
  • (27)4.8 习题课
  • (AngularJS)Angular 控制器之间通信初探
  • (LeetCode C++)盛最多水的容器
  • (超简单)构建高可用网络应用:使用Nginx进行负载均衡与健康检查
  • (附源码)ssm考试题库管理系统 毕业设计 069043
  • (十)T检验-第一部分
  • (一一四)第九章编程练习
  • (转)chrome浏览器收藏夹(书签)的导出与导入
  • (转)拼包函数及网络封包的异常处理(含代码)
  • (转)如何上传第三方jar包至Maven私服让maven项目可以使用第三方jar包
  • .jks文件(JAVA KeyStore)
  • .NET 4.0中的泛型协变和反变
  • .NET C# 使用 SetWindowsHookEx 监听鼠标或键盘消息以及此方法的坑
  • .NET Core SkiaSharp 替代 System.Drawing.Common 的一些用法
  • .net on S60 ---- Net60 1.1发布 支持VS2008以及新的特性
  • .net 发送邮件
  • .NET命令行(CLI)常用命令
  • .net通用权限框架B/S (三)--MODEL层(2)