【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的区别
AOP (**A**spect **O**riented Programming),是一种思想,即面向切面编程
Spring AOP 则是一个框架,Spring项目中需要引入依赖而使用
我们要实现用户登录校验的功能,没有实现AOP之前,我们只能这样做:
博客系统登录功能实现,博客传送门:【JavaEE】前后端综合项目-博客系统(下)_s:103的博客-CSDN博客
无论是哪种,都有这样的特性,就是代码耦合度高,网页的每个功能都要各自实现“登录校验”的代码,这样的坏处是:
图示:
刚才说了,AOP是面向切面编程,这是英语直译的结果,不用太多理会~
有了AOP后,我们只需要在代码的某一处配置一下,所有的功能就能实现用户登录校验了,不再需要重复写那些代码了~
切面可以理解为,切下来的一个方面,一个步骤
切下来后有种藕断丝连的感觉:
例如这个图,再等一下讲解AOP的组成之后,回头看可能会有更好的理解~
如果把切面看成动作执行者,✂
- 我们可以将切面形象地比喻为一把剪刀。
- 剪刀可以在不改变原始材料的情况下,将其切割成不同的形状
- 同样,切面在编程中也可以在不修改原始代码的情况下,将横切关注点应用到不同的对象或方法上
- 在代码实现的时候,将需要的统一处理的功能,“剪”下来进行统一处理
- 就像剪刀可以将材料切割成不同的形状一样,切面可以将横切关注点切割并应用到代码的不同部分,从而实现代码的模块化和重用
例如,调用功能1的时候,会通过切下来的“面”的匹配对应的“块”,之后进行“组装”~
- 这样就在调用功能1之前进行了登录校验
好处:
AOP就很适合解决这种功能统一,且是使用的地方较多的功能了
除了登录校验外,还可以实现:
也可以说,AOP面向了多个对象
也就是说,AOP是OOP(Object Oriented Programming,面向对象编程)的一个补充和完善
Spring AOP框架内部实现了AOP,开发者按照规则写下的代码,就对应着AOP逻辑
Spring AOP的学习分为以下三步:
一个Aspect代表一个“统一处理”,因为统一设计原则,一个切面就是一个功能,例如“登录校验”
如果把这些定义,看成“切面”的独一无二的横切面,看成标识,切面就对应那个“块”,也就是功能,所以切面就看成一个功能~
即,AOP是干啥的
规定 这个切面是从哪些,前后端交互接口,“剪”下来的
AOP执行的具体方法
有可能触发切点的所有点
通过代码实现,你可能会有更切合的体验!
你会发现,在IDEA的勾选选入依赖里,没有AOP这个选项,这也很正常,因为并不是所有依赖都包含在其中!
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-aopartifactId>
dependency>
一个切面其实就是一个类,加上@Aspect注解,这个类就是为了实现某个“统一处理”的
一个方法加上注解@Pointcut,在括号内写一些语句,就定义了一个切点
execution(* com.example.demo.controller.TestController.*(..))
,解析:
execution()
,执行括号中提及的方法,就触发切点*
,不限制方法权限(public、private…),全部方法com.example.demo.controller.TestController.
,针对的类的位置*(..)
,代表类中的所有方法
*
,所有的方法名(..)
,任意的参数列表
对于连接点,则是刚才切点对应的前后端交互接口:
我们在这里不需要在意其他业务,只需要专注开发,而Aspect的代码开发里则面向了这几个连接点!
为了与通知的方法区分,我在控制台打印信息:
通知就是访问对应接口的时候,要执行的业务,分为五种通知:
顾名思义,区分就是,通知执行的时机~
对应五种注解(加在一个方法的上面,此方法被称为通知方法):
// 前置通知
@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 ⽅法");
}
注解括号内代表,对应的切点方法
效果:
按多次:
// 抛出异常之前通知
@AfterThrowing("pointcut()")
public void doAfterThrowing(){
System.out.println("执⾏ doAfterThrowing ⽅法");
}
对于异常通知的触发案例,暂时不介绍
自定义行为的通知,可以模拟其他通知~
@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,代表着连接点对象
记得返回这个object,不然框架处理不了返回值作为响应!
效果:
这样也看出了优先级~
环绕通知,更灵活
更好的实现“原子性”,通过加锁就行,如执行时间统计…
如后置通知方法需要跟前置通知方法有“数据交互”
Spring AOP 是构建在**动态代理的基础上,因此Spring 对 AOP的支持局限于方法级的拦截**
原本访问目标对象:
AOP之后:
就像fiddler一样,代理了请求,期间保留了其信息…
通过代理类,目标对象Join Point何时执行目标方法,代理说了算
我们不通过Spring AOP框架,我们只能自己实现AOP才能实现在目标方法调用之前和调用之后…时机进行一些业务!
通过这两种动态代理的实现~
文章到此结束!谢谢观看
可以叫我 小马,我可能写的不好或者有错误,但是一起加油鸭!不得不提的是,切面、切点、连接点、通知,这些名词,不要纠结他们为啥这么叫,咱们知道他们的含义,知道Spring AOP怎么开发就行了~
代码:spring_aop-demo · 游离态/马拉圈2023年8月 - 码云 - 开源中国 (gitee.com)