0
点赞
收藏
分享

微信扫一扫

[Spring Framework]AOP工作流程


文章目录

  • ​​AOP工作流程​​
  • ​​基本流程​​
  • ​​验证​​
  • ​​核心概念​​

AOP工作流程

由于AOP是基于Spring容器管理的bean做的增强,所以整个工作过程需要从Spring加载bean说起:

基本流程

流程1:Spring容器启动

  • 容器启动就需要去加载bean,哪些类需要被加载呢?
  • 需要被增强的类,如:BookServiceImpl
  • 通知类,如:MyAdvice
  • 注意此时bean对象还没有创建成功

流程2:读取所有切面配置中的切入点

[Spring Framework]AOP工作流程_目标对象

  • 上面这个例子中有两个切入点的配置,但是第一个​​ptx()​​并没有被使用,所以不会被读取。

流程3:初始化bean

判定bean对应的类中的方法是否匹配到任意切入点

  • 注意第1步在容器启动的时候,bean对象还没有被创建成功。
  • 要被实例化bean对象的类中的方法和切入点进行匹配
  • [Spring Framework]AOP工作流程_后端_02

  • 匹配失败,创建原始对象,如​​UserDao​
  • 匹配失败说明不需要增强,直接调用原始对象的方法即可。
  • 匹配成功,创建原始对象(目标对象)的代理对象,如:​​BookDao​
  • 匹配成功说明需要对其进行增强
  • 对哪个类做增强,这个类对应的对象就叫做目标对象
  • 因为要对目标对象进行功能增强,而采用的技术是动态代理,所以会为其创建一个代理对象
  • 最终运行的是代理对象的方法,在该方法中会对原始方法进行功能增强

流程4:获取bean执行方法

  • 获取的bean是原始对象时,调用方法并执行,完成操作
  • 获取的bean是代理对象时,根据代理对象的运行模式运行原始方法与增强的内容,完成操作

验证

为了验证IOC容器中创建的对象和我们刚才所说的结论是否一致,首先先把结论理出来:

  • 如果目标对象中的方法会被增强,那么容器中将存入的是目标对象的代理对象
  • 如果目标对象中的方法不被增强,那么容器中将存入的是目标对象本身。

首先我们把@Before注掉,这样通知与切入点失去联系,目标对象中的方法没有被增强:

[Spring Framework]AOP工作流程_加载_03


然后我们执行以下代码:

public class App11 {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao2 bookDao = ctx.getBean("BookDao4", BookDao2.class);
// bookDao.save();
// bookDao.update();

System.out.println(bookDao.getClass());

}
}

[Spring Framework]AOP工作流程_spring_04

我们去取消注释使方法被增强,然后再次运行程序,结果如下:

[Spring Framework]AOP工作流程_加载_05

核心概念

在上面介绍AOP的工作流程中,我们提到了两个核心概念,分别是:

  • ​目标对象(Target)​​:原始功能去掉共性功能对应的类产生的对象,这种对象是无法直接完成最终工作的
  • ​代理(Proxy)​​:目标对象无法直接完成工作,需要对其进行功能回填,通过原始对象的代理对象实现

上面这两个概念比较抽象,简单来说,

目标对象就是要增强的类[如:BookServiceImpl类]对应的对象,也叫原始对象,不能说它不能运行,只能说它在运行的过程中对于要增强的内容是缺失的。

SpringAOP是在不改变原有设计(代码)的前提下对其进行增强的,它的底层采用的是代理模式实现的,所以要对原始对象进行增强,就需要对原始对象创建代理对象,在代理对象中的方法把通知[如:MyAdvice中的method方法]内容加进去,就实现了增强,这就是我们所说的代理(Proxy)。


举报

相关推荐

0 条评论