专门做网站制作的公司,偃师网站开发,网站制作一般多少钱,深圳电商网站开发公司1 什么是Spring AOP
要想知道Spring AOP那必然是是要先知道什么是AOP了: AOP#xff0c;全称为 Aspect-Oriented Programming#xff08;面向切面编程#xff09;#xff0c;是一种编程范式#xff0c;用于提高代码的模块化#xff0c;特别是横切关注点#xff08;cros…1 什么是Spring AOP
要想知道Spring AOP那必然是是要先知道什么是AOP了: AOP全称为 Aspect-Oriented Programming面向切面编程是一种编程范式用于提高代码的模块化特别是横切关注点cross-cutting concerns的模块化。横切关注点是指那些影响多个模块的功能比如日志记录、安全性、事务管理等。AOP 通过将这些关注点与业务逻辑分离简化代码维护提高代码的可读性和可重用性。 ⽐如用户登录权限的效验没学 AOP 之前我们所有需要判断⽤户登录的⻚⾯中 的⽅法都要各⾃实现或调用用户验证的⽅法然⽽有了 AOP 之后我们只需要在某⼀处配 置⼀下所有需要判断用户登录页面中的⽅法就全部可以实现⽤户登录验证了不再需要每 个⽅法中都写相同的用户登录验证了。 AOP 是⼀种思想而Spring AOP 是⼀个框架提供了⼀种对 AOP 思想的实现它们的关系和IoC 与 DI 类似。 2 为什么要使用AOP 想象⼀个场景我们在做后台系统时除了登录和注册等⼏个功能不需要做⽤户登录验证之外其他⼏乎所有⻚⾯调⽤的前端控制器 Controller都需要先验证⽤户登录的状态那这个时候我们要怎么处 理呢 如果每个 Controller 都要写⼀遍⽤户登录验证然⽽当功能越来越多那么要写的登录验证也越来越多⽽这些⽅法⼜是相同的这么多的⽅法就会代码修改和维护的成本。那有没 有简单的处理⽅案呢答案是有的对于这种功能统⼀且使⽤的地⽅较多的功能就可以考虑 AOP 来统同一处理。 AOP面向切面编程不仅可以用于统一的用户登录判断还可以用于处理各种横切关注点。以下是一些常见的应用场景 1. 日志记录 AOP 可以在方法执行前后自动记录日志无需在每个方法中显式编写日志代码从而保持业务逻辑的简洁。例如可以在方法调用之前记录方法名称和参数在方法成功执行之后记录返回值。 2. 性能监控 AOP 可以用于记录方法执行时间计算方法执行的时间从而实现性能监控。这对于识别和优化性能瓶颈非常有用。 3. 事务管理 AOP 可以用于声明式事务管理。在方法执行前开启事务执行成功后提交事务发生异常时回滚事务从而简化事务处理逻辑。 4. 安全控制 AOP 可以在方法执行前检查用户权限如果用户没有相应权限则抛出异常阻止方法执行。这可以集中处理安全逻辑避免在每个方法中重复代码。 5. 异常处理 AOP 可以在方法执行时捕获异常并统一处理例如记录错误日志或发送通知。这样可以提高代码的可维护性和一致性。 也就是说使⽤ AOP 可以扩充多个对象的某个能⼒所以 AOP 可以说是 OOPObject Oriented Programming⾯向对象编程的补充和完善。 3 Spring AOP该怎么学习 Spring AOP 学习主要分为以下 3 个部分 学习 AOP 组成的相关概念。 学习 Spring AOP 使⽤。 学习 Spring AOP 实现原理。 3.1 相关概念 1 切面Aspcet 切面可以理解为某一模块化的功能的具体内容比如登录判断就是一个切面而是日志的统计记录又是一个切面。切面是模块化的关注点它可以跨越多个对象。切面通常包括横切关注点的行为和逻辑比如日志记录、性能监视、事务管理等。 切⾯Aspect由切点Pointcut和通知Advice组成它既包含了横切逻辑的定义也包括了连接点的定义。 2 切点Pointcut 切点用来定义一个拦截规则。 Pointcut 的作⽤就是提供⼀组规则使⽤ AspectJ pointcut expression language 来描述来匹配 Join Point给满⾜规则的 Join Point 添加 Advice 3 通知Advice 定义了拦截规则之后肯定需要“做点什么”这就是通知干的事情。可以理解为执行AOP的逻辑业务。通知是切面在连接点处执行的代码。通知可以在方法调用之前、之后或者异常抛出时执行。 常见的通知类型包括 Before adviceBefore前置通知在方法调用之前执行。After adviceAfter后置通知在方法调用之后执行。Around adviceAround环绕通知在方法调用之前和之后执行。After returning adviceAfterReturn返回通知在方法成功返回之后执行。After throwing adviceAtferThroeing异常通知在方法抛出异常之后执行。 4 连接点Join Point 连接点是程序执行过程中可以插入切面的一个点。这些点可以是方法调用、方法执行、对象实例化等。所有可能触发切点的点都可以叫作连接点。 AOP 整个组成部分的概念如下图所示以多个⻚⾯都要访问⽤户登录权限为例 3.2 上手使用 接下来我们使⽤ Spring AOP 来实现⼀下 AOP 的功能完成的⽬标是拦截所有 UserController ⾥⾯的所有⽅法每次调⽤ UserController 中任意⼀个⽅法时都执⾏相应的通知事件。 Spring AOP 的实现步骤如下 添加 Spring AOP 框架⽀持。 定义切⾯和切点。 定义通知 3.2.1 添加Spring Boot AOP框架支持 注意在maven仓库中添加的时候搜索的是spring-boot-starter-aop因为目前我使用的是spring boot项目如果是spring core项目的话就需要的是原生的spring aop依赖。他们两者是不一样的。 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-aop/artifactId
/dependency 可以看到我们使用的注解是来自aspectj 3.2.2 定义切面和切点 定义切面就是在我们需要的类上添加一个Aspect注解这个类可以跨越多个对象。现在我创建了一个UserAOP就是针对UserController的一个切面。 创建切点这里只用注解Pointcut后面跟的就是具体地拦截规则代码中的规则就是拦截UserController下面的所有方法。拦截规则描述语言aspectj语法的使用大家感兴趣可以自己检索相关资料查看。下面是简单的介绍 AspectJ ⽀持三种通配符 * 匹配任意字符只匹配⼀个元素包类或⽅法⽅法参数 .. 匹配任意字符可以匹配多个元素 在表示类时必须和 * 联合使⽤。 表示按照类型匹配指定类的所有类必须跟在类名后⾯如 com.cad.Car ,表示继承该类的所有⼦类包括本身。 切点表达式由切点函数组成其中 execution() 是最常⽤的切点函数⽤来匹配⽅法语法为 execution(修饰符返回类型包.类.⽅法(参数)异常) 下面先来通过案例直接使用AOP试一试。这是讲的最原生的使用实际开发也不会使用这里重在AOP思想。 3.2.3 创建通知 我们创建了切面切点肯定是要执行一些事情的这些事情就是通知要做的。代码中简单的使用了一个前置通知和一个后置通知通知就是做一个打印帮助观察代码的执行结果。 各种通知的创建demo package com.example.springaopdemo.controller;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;RestController
RequestMapping(user)
public class UserController {RequestMapping(sayhi)public String sayHi(){System.out.println(执行了 sayHi 方法);return hi springboot AOP;}RequestMapping(login)public String login(){System.out.println(执行了 login 方法);return do user login;}// return 之前通知AfterReturning(pointcut())public void doAfterReturning(){System.out.println(执⾏ AfterReturning ⽅法);}// 抛出异常之前通知AfterThrowing(pointcut())public void doAfterThrowing(){System.out.println(执⾏ doAfterThrowing ⽅法);}// 添加环绕通知Around(pointcut())public Object doAround(ProceedingJoinPoint joinPoint){Object obj null;System.out.println(Around ⽅法开始执⾏);try {// 执⾏拦截⽅法obj joinPoint.proceed();} catch (Throwable throwable) {throwable.printStackTrace();}System.out.println(Around ⽅法结束执⾏);return obj;}
}3.2.4 创建连接点 没有连接点AOP就形同虚设啊通过连接点触发切点执行各种通知。连接点是程序执行过程中可以插入切面的一个点。这些点可以是方法调用、方法执行、对象实例化等。 同时为了验证我们的切点定义的拦截规则是否起作用在设置一个对照类如果我们的UserController促发了切点的通知而访问其他的Controller没有触发通知就说明我们的AOP是可以正常Work的。 执行代码观察结果 http://127.0.0.1:8080/user/sayhi 可以发现现在访问UserController中的方法已经成功的被拦截到但是我们没有做拦截业务直接放行了如果是对于验证登陆来讲我们在拦截后可以直接返回未登陆的状态码。 那么我们现在来访问设置的对照组的Controller中的方法会不会被拦截呢 http://127.0.0.1:8080/article/sayhi 很明显是没有促发切点执行通知时间也就是没有被拦截。
这也说明了我们的代码逻辑是没有问题的。
3.3 Spring AOP实现原理
Spring AOP是构建在动态代理基础之上的因此Spring对AOP的支持局限于方法级别的拦截。 Spring AOP ⽀持 JDK Proxy 和 CGLIB ⽅式实现动态代理。默认情况下实现了接⼝的类使用 AOP 会基于 JDK ⽣成代理类没有实现接⼝的类会基于 CGLIB ⽣成代理类。 这里先介绍一下AOP中最后的一个关键概念 织⼊Weaving代理的生成时机 织⼊是把切⾯应⽤到⽬标对象并创建新的代理对象的过程切⾯在指定的连接点被织⼊到⽬标对象中。在⽬标对象的⽣命周期⾥有多个点可以进⾏织⼊ 编译期切⾯在⽬标类编译时被织⼊。这种⽅式需要特殊的编译器。AspectJ的织⼊编译器就是以这种⽅式织⼊切⾯的。 类加载期切⾯在⽬标类加载到JVM时被织⼊。这种⽅式需要特殊的类加载器ClassLoader,它可以在⽬标类被引⼊应⽤之前增强该⽬标类的字节码。AspectJ5的加载时织⼊load-time weaving. LTW就⽀持以这种⽅式织⼊切⾯。 运⾏期切⾯在应⽤运⾏的某⼀时刻被织⼊。⼀般情况下在织⼊切⾯时AOP容器会为⽬标对象动态创建⼀个代理对象。SpringAOP就是以这种⽅式织⼊切⾯的。 既然有 JDK Proxy 和 CGLIB 这两种方式那就要需要了解这两种方法的不同了
JDK 和 CGLIB 实现的区别
JDK 实现要求被代理类必须实现接⼝之后是通过 InvocationHandler 及 Proxy在运⾏ 时动态的在内存中⽣成了代理类对象该代理对象是通过实现同样的接⼝实现类似静态代 理接⼝实现的⽅式只是该代理类是在运⾏期时动态的织⼊统⼀的业务逻辑字节码来完成。 也就是说没有实现接口的类就没有办法实现AOP了没错所以就需要CGLIB了。底层实现原理反射CGLIB 实现被代理类可以不实现接⼝是通过继承被代理类在运⾏时动态的⽣成代理类对象所以他不能代理被final修饰的类。 底层实现原理字节码增强技术JDK动态代理相对性能较高生成代理对象速度较快CGLIB动态代理性能相对较低生成代理速度较慢。【jdk1.7以后】 总结
AOP 是对某方面能力的统一实现它是一种实现思想Spring AOP 是对 AOP 的具体实现AOP 可通过 AspectJ(注解)的方式来实现 AOP 的功能,Spring AOP的实现步骤是 1. 添加 AOP 框架⽀持。 2. 定义切⾯和切点。 3. 定义通知。 Spring AOP 是通过动态代理的⽅式在运⾏期将 AOP 代码织⼊到程序中的它的实现⽅式有两种JDK Proxy 和 CGLIB。