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

Spring |(七)AOP概念及工作流程

文章目录

  • 📚AOP简介
  • 📚AOP入门案例
    • 🐇环境准备
    • 🐇AOP实现步骤
  • 📚AOP工作流程
  • 📚小结

学习来源:黑马程序员SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术

📚AOP简介

  • 一句话描述:AOP是在不改原有代码的前提下对其进行增强。

  • AOP(Aspect Oriented Programming)面向切面编程,一种编程范式,指导开发者如何组织程序结构。

  • 以下述代码为例,计算万次执行消耗时间的代码只有save有,但最后deleteupdate方法最终都执行了万次,这里就用到了AOP——在不惊动(改动)原有设计(代码)的前提下,想给谁添加功能就给谁添加。

    @Repository
    public class BookDaoImpl implements BookDao {public void save() {//记录程序当前执行执行(开始时间)Long startTime = System.currentTimeMillis();//业务执行万次for (int i = 0;i<10000;i++) {System.out.println("book dao save ...");}//记录程序当前执行时间(结束时间)Long endTime = System.currentTimeMillis();//计算时间差Long totalTime = endTime-startTime;//输出信息System.out.println("执行万次消耗时间:" + totalTime + "ms");}public void update(){System.out.println("book dao update ...");}public void delete(){System.out.println("book dao delete ...");}public void select(){System.out.println("book dao select ...");}
    }
    

    在这里插入图片描述

    • 对于上面的案例中BookServiceImpl中有saveupdatedeleteselect方法,这些方法叫连接点
    • 在BookServiceImpl的四个方法中,updatedelete只有打印没有计算万次执行消耗时间,但是在运行的时候已经有该功能,那也就是说updatedelete方法都已经被增强,所以对于需要增强的方法我们叫切入点
    • 执行BookServiceImpl的update和delete方法的时候都被添加了一个计算万次执行消耗时间的功能,将这个功能抽取到一个方法中,换句话说就是存放共性功能的方法,我们叫通知
    • 通知是要增强的内容,会有多个,切入点是需要被增强的方法,也会有多个,那哪个切入点需要添加哪个通知,就需要提前将它们之间的关系描述清楚,那么对于通知和切入点之间的关系描述,我们叫切面
    • 通知是一个方法,方法不能独立存在需要被写在一个类中,这个类叫通知类
      在这里插入图片描述
  • 归纳一下

    • 连接点(JoinPoint):程序执行过程中的任意位置,粒度为执行方法、抛出异常等。
    • 切入点(Pointcut):匹配连接点的式子。
    • 通知(Advice):在切入点处执行的操作,也就是共性功能
    • 通知类:定义通知的类。
    • 切面(Aspect):描述通知与切入点的对应关系。

📚AOP入门案例

🐇环境准备

在这里插入图片描述

  • 创建一个Maven项目。

  • pom.xml添加Spring依赖。

    <dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.10.RELEASE</version></dependency>
    </dependencies>
    
  • 添加BookDao和BookDaoImpl类。

    public interface BookDao {public void save();public void update();
    }@Repository
    public class BookDaoImpl implements BookDao {public void save() {System.out.println(System.currentTimeMillis());System.out.println("book dao save ...");}public void update(){System.out.println("book dao update ...");}
    }
    
  • 创建Spring的配置类

    @Configuration
    @ComponentScan("com.itheima")
    public class SpringConfig {
    }
    
  • 编写App运行类

    public class App {public static void main(String[] args) {ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);BookDao bookDao = ctx.getBean(BookDao.class);bookDao.save();}
    }
    

需求:使用SpringAOP的注解方式完成在方法执行前打印出当前系统时间。

  • 目前打印save方法的时候,因为方法中有打印系统时间,所以运行的时候是可以看到系统时间。
  • update就没有该功能。我们要使用SpringAOP的方式在不改变update方法的前提下让其具有打印系统时间的功能。

🐇AOP实现步骤

  • 步骤1:pom.xml添加依赖。spring-context中已经导入了spring-aop,所以不需要再单独导入spring-aop。导入AspectJ的jar包,AspectJ是AOP思想的一个具体实现。
    <dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.4</version>
    </dependency>
    
  • 步骤2:定义接口与实现类。这里沿用环境准备的部分,不作修改。
  • 步骤3:定义通知类和通知。通知即将共性功能抽取出来后形成的方法,共性功能指当前系统时间的打印。
    //类名和方法名任意
    public class MyAdvice {public void method(){System.out.println(System.currentTimeMillis());}
    }
    
  • 步骤4:定义切入点。切入点定义依托一个不具有实际意义的方法进行,即无参数、无返回值、方法体无实际逻辑。
    ublic class MyAdvice {@Pointcut("execution(void com.itheima.dao.BookDao.update())")private void pt(){}public void method(){System.out.println(System.currentTimeMillis());}
    }
    
  • 步骤5:制作切面。绑定切入点与通知关系,并指定通知添加到原始连接点的具体执行位置
    public class MyAdvice {@Pointcut("execution(void com.itheima.dao.BookDao.update())")private void pt(){}@Before("pt()")public void method(){System.out.println(System.currentTimeMillis());}
    }
    
    在这里插入图片描述
  • 步骤6:将通知类配给给容器并标识其为切面类。
    @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());}
    }
    
  • 步骤7:开启注解格式AOP功能。
    @Configuration
    @ComponentScan("com.itheima")
    @EnableAspectJAutoProxy
    public class SpringConfig {
    }
    
  • 步骤8:运行程序。在执行update方法之前打印了系统时间戳,说明对原始方法进行了增强,AOP编程成功。
    public class App {public static void main(String[] args) {ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);BookDao bookDao = ctx.getBean(BookDao.class);bookDao.update();}
    }
    
    在这里插入图片描述

📚AOP工作流程

  • 流程1:Spring容器启动。
    • 容器启动就需要去加载bean,去加载那些需要被增强的类,如BookServiceImpl,通知类,如MyAdvice。
    • 注意此时bean对象还没有创建成功。
  • 流程2:读取所有切面配置中的切入点。
    • 下面这个例子中有两个切入点的配置。
    • 但第一个ptx()并没有被使用,所以不会被读取。
      在这里插入图片描述
  • 流程3:初始化bean,判定bean对应的类中的方法是否匹配到任意切入点。
    • 第1步在容器启动的时候,bean对象还没有被创建成功。
    • 要被实例化bean对象的类中的方法和切入点进行匹配。
      在这里插入图片描述
      • 匹配失败,创建原始对象,如UserDao。匹配失败说明不需要增强,直接调用原始对象的方法即可。
      • 匹配成功,创建原始对象(目标对象)代理对象,如BookDao
        • 匹配成功说明需要对其进行增强。对哪个类做增强,这个类对应的对象就叫做目标对象。
        • 因为要对目标对象进行功能增强,采用的技术是动态代理,所以会为其创建一个代理对象。
        • 最终运行的是代理对象的方法,在该方法中会对原始方法进行功能增强。
  • 流程4:获取bean执行方法。
    • 获取的bean是原始对象时,调用方法并执行,完成操作。
    • 获取的bean是代理对象时,根据代理对象的运行模式运行原始方法与增强的内容,完成操作。

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

📚小结

  • 知识点1:@EnableAspectJAutoProxy
    在这里插入图片描述
  • 知识点2:@Aspect
    在这里插入图片描述
  • 知识点3:@Pointcut
    在这里插入图片描述
  • 知识点4:@Before
    在这里插入图片描述

http://www.mrgr.cn/news/78367.html

相关文章:

  • 解析生成对抗网络(GAN):原理与应用
  • 三维地形图计算软件(三)-原基于PYQT5+pyqtgraph旧代码
  • 蓝牙定位的MATLAB仿真程序|基于信号强度的定位,平面、四个蓝牙基站(附源代码)
  • Ubuntu 环境下的 C/C++ 编译与调试配置
  • MyBatis 操作数据库(进阶)
  • 开源TTS语音克隆神器GPT-SoVITS_V2版本地整合包部署与远程使用生成音频
  • paimon的四种changelog模式(2)-none模式
  • linux模拟HID USB设备及wireshark USB抓包配置
  • Qt中QGraphics绘图类相关解释
  • Linux一篇通
  • 【TQ2440】02 串口连接进入u-boot
  • 【CSS in Depth 2 精译_061】9.4 CSS 中的模式库 + 9.5 本章小结
  • pta 题目(3)
  • 服务器记录所有用户docker操作,监控删除容器/镜像的人
  • 自动化运维(k8s)之微服务信息自动抓取:namespaceName、deploymentName等全解析
  • ComfyUI节点安装笔记
  • 数据结构--图
  • 【NLP 3、深度学习简介】
  • 1-深度学习干货总结(持续更新)
  • Matlab Simulink HDL Coder FPGA开发初体验—计数器
  • 表征对齐在训练DiT模型中的重要性
  • 【算法 python A*算法的实现】
  • 某j,mybatis-plus,多租户,多表关联查询 ,主表不追加租户条件bug解决
  • element ui select绑定的值是对象的属性时,显示异常.
  • SAP学习
  • Android 图形系统之一:概览