前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >13. AOP工作流程

13. AOP工作流程

作者头像
捞月亮的小北
发布2023-12-01 10:19:38
1180
发布2023-12-01 10:19:38
举报
文章被收录于专栏:捞月亮的小北

3.1 AOP 工作流程

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

流程 1:Spring 容器启动
  • 容器启动就需要去加载 bean,哪些类需要被加载呢?
  • 需要被增强的类,如:BookServiceImpl
  • 通知类,如:MyAdvice
  • 注意此时 bean 对象还没有创建成功
流程 2:读取所有切面配置中的切入点

image
image

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

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

  • 注意第 1 步在容器启动的时候,bean 对象还没有被创建成功。
  • 要被实例化 bean 对象的类中的方法和切入点进行匹配

image
image

  • 匹配失败,创建原始对象,如UserDao
    • 匹配失败说明不需要增强,直接调用原始对象的方法即可。
  • 匹配成功,创建原始对象(目标对象)的代理对象,如:BookDao
    • 匹配成功说明需要对其进行增强
    • 对哪个类做增强,这个类对应的对象就叫做目标对象
    • 因为要对目标对象进行功能增强,而采用的技术是动态代理,所以会为其创建一个代理对象
    • 最终运行的是代理对象的方法,在该方法中会对原始方法进行功能增强
流程 4:获取 bean 执行方法
  • 获取的 bean 是原始对象时,调用方法并执行,完成操作
  • 获取的 bean 是代理对象时,根据代理对象的运行模式运行原始方法与增强的内容,完成操作
验证容器中是否为代理对象

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

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

1.要执行的方法,不被定义的切入点包含,即不要增强,打印当前类的 getClass()方法 2.要执行的方法,被定义的切入点包含,即要增强,打印出当前类的 getClass()方法 3.观察两次打印的结果

步骤 1:修改 App 类,获取类的类型
代码语言:javascript
复制
public class App {
    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        BookDao bookDao = ctx.getBean(BookDao.class);
        System.out.println(bookDao);
        System.out.println(bookDao.getClass());
    }
}
步骤 2:修改 MyAdvice 类,不增强

因为定义的切入点中,被修改成update1​,所以 BookDao 中的 update 方法在执行的时候,就不会被增强,

所以容器中的对象应该是目标对象本身。

代码语言:javascript
复制
@Component
@Aspect
public class MyAdvice {
    @Pointcut("execution(void com.itheima.dao.BookDao.update1())")
    private void pt(){}

    @Before("pt()")
    public void method(){
        System.out.println(System.currentTimeMillis());
    }
}
步骤 3:运行程序

image
image

步骤 4:修改 MyAdvice 类,增强

因为定义的切入点中,被修改成update​,所以 BookDao 中的 update 方法在执行的时候,就会被增强,

所以容器中的对象应该是目标对象的代理对象

代码语言:javascript
复制
@Component
@Aspect
public class MyAdvice {
    @Pointcut("execution(void com.itheima.dao.BookDao.update())")
    private void pt(){}

    @Before("pt()")
    public void method(){
        System.out.println(System.currentTimeMillis());
    }
}
步骤 5:运行程序

image
image

至此对于刚才的结论,我们就得到了验证,这块大家需要注意的是:

不能直接打印对象,从上面两次结果中可以看出,直接打印对象走的是对象的 toString 方法,不管是不是代理对象打印的结果都是一样的,原因是内部对 toString 方法进行了重写。

3.2 AOP 核心概念

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

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

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

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

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

小结

通过这一节中,我们需要掌握的内容有:

  • 能说出 AOP 的工作流程
  • AOP 的核心概念
    • 目标对象、连接点、切入点
    • 通知类、通知
    • 切面
    • 代理
  • SpringAOP 的本质或者可以说底层实现是通过代理模式。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-06-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 3.1 AOP 工作流程
    • 流程 1:Spring 容器启动
      • 流程 2:读取所有切面配置中的切入点
        • 流程 3:初始化 bean,
          • 流程 4:获取 bean 执行方法
            • 验证容器中是否为代理对象
              • 验证思路
              • 步骤 1:修改 App 类,获取类的类型
              • 步骤 2:修改 MyAdvice 类,不增强
              • 步骤 3:运行程序
              • 步骤 4:修改 MyAdvice 类,增强
              • 步骤 5:运行程序
          • 3.2 AOP 核心概念
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档