Spring的另一大的特征:AOP

2024-02-26 06:44
文章标签 java spring 特征 aop 一大

本文主要是介绍Spring的另一大的特征:AOP,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • AOP (Aspect Oriented Programming)
  • AOP 入门案例(注解版)
  • AOP 工作流程——代理
  • AOP切入点表达式
  • AOP 通知类型
  • AOP通知获取数据
    • 获取切入点方法的参数
    • 获取切入点方法返回值
    • 获取切入点方法运行异常信息
  • 百度网盘分享链接输入密码数据错误兼容性处理

AOP (Aspect Oriented Programming)

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

OOP (Object Oriented Programming) 面向对象编程

  • AOP 的作用: 在不惊动原始设计的基础上为其进行功能增强
  • Spring 理念: 无入侵式/无侵入式

在这里插入图片描述

  • 连接点(JointPoint): 程序执行过程中的任意位置,粒度为执行方法、抛出异常、设置变量等。

    • 在 SpringAOP 中,理解为方法的执行
  • 切入点(Pointcut): 匹配连接点的式子

    • 在 SpringAOP 中,一个切入点可以只描述一个具体方法,也可以匹配多个方法
      • 一个具体方法:eg : com.itheima.dao包下的BookDao接口中的无形参无返回值的save方法
      • 匹配多个方法:eg : 所有的save方法,所有的get开头的方法,所有以Dao结尾的接口中的任意方法,所有带有一个参数的方法
  • 通知(Advice): 在切入点处执行的操作,也就是共性功能

    • 在 SpringAOP 中,功能最终以方法的形式呈现
  • 通知类: 定义通知的类

  • 切面(Aspect): 描述通知与切入点的对应关系

AOP 入门案例(注解版)

- 导入 aop 相关坐标
    <dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.4</version></dependency>

spring-context 坐标依赖 spring-aop 坐标
在这里插入图片描述

    • 定义dao 接口与实现类
public interface BookDao {public void save();public void update();public void delete();public void select();
}
@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 ...");}
}
    • 定义通知类,制作通知
    • 定义切入点:切入点定义依托一个不具有实际意义的方法进行,即无参数,无返回值,方法体无实际逻辑
    • 绑定切入点与通知关系,并指定通知添加到原始连接点的具体执行位置
    • 定义通知类受Spring容器管理,并定义当前类为切面类
@Component
@Aspect
public class MyAdvice {@Pointcut("execution(* com.itheima.dao.BookDao.*d*(..))")private void pt(){}@Around("pt()")public Object around(ProceedingJoinPoint pjp) throws Throwable {System.out.println("------------------------------");Long startTime = System.currentTimeMillis();for (int i = 0 ; i<10000 ; i++) {//调用原始操作pjp.proceed();}Long endTime = System.currentTimeMillis();Long totalTime = endTime-startTime;System.out.println("执行万次消耗时间:" + totalTime + "ms");return null;}}
    • 开启 Spring 对 AOP 注解驱动支持 : @EnableAspectJAutoProxy
@Configuration
@ComponentScan("com.itheima")
@EnableAspectJAutoProxy
public class SpringConfig {
}

AOP 工作流程——代理

  1. Spring 容器启动
  2. 读取所有切面配置中的切入点
  3. 初始化bean,判定bean对应的类中的方法是否匹配到任意切入点
    • 匹配失败,创建对象
    • 匹配成功,创建原始对象(目标对象)的代理对象
  4. 获取bean执行方法
    • 获取bean,调用方法并执行,完成操作
    • 获取bean是代理对象时, 根据代理对象的运行模式运行原始方法与增强的内容,完成操作
  • 目标对象(Target) : 原始功能去掉共性功能对应的类产生的对象,这种对象是无法直接完成最终工作的。
  • 代理(Proxy) : 目标对象无法直接完成工作,需要对其进行功能回填,通过原始对象的代理对象实现

AOP切入点表达式

  • 切入点:要进行增强的方法
  • 切入点表达式:要进行增强的方法的描述方式

在这里插入图片描述

  • 切入点表达式标准格式: 动作关键字 (访问修饰符 返回值 包名.类/接口名.方法名(参数)异常名)
execution (public User com.itheima.service.UserService.findById (int))
    • 动作关键字: 描述切入点的行为动作,例如execution表示执行到指定切入点
    • 访问修饰符: public , private 等 可省略
    • 返回值
    • 包名
    • 类/接口名
    • 方法名
    • 参数
    • 异常名:方法定义中抛出指定异常,可省略
  • 可以使用通配符描述切入点,快速描述:

    • eg: * : 单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的匹配符出现
execution (public * com.itheima.*.UserService.find* (*))

匹配com.itheima包下的任意包中的UserService类或接口中所有find开头的带有一个参数的方法

    • eg: . . :多个连续的任意符号,可以独立出现,常用于简化包名与参数的书写
execution (public User com..UserService.findById (..))

匹配com包下的任意包中的UserService类或接口中所有名称为findByld的方法

    • eg: + :专用于匹配子类类型
execution (* *..*Service+.*(..))

AOP 通知类型

  • AOP 通知描述了抽取的共性功能,根据共性功能抽取的位置不同,最终运行代码时要将其加入到合理的位置
  • 5 种类型
    • 前置通知
    • 后置通知
    • 环绕通知 (重点) :通过ProceedingJoinPoint 对原始方法调用,获得返回值,最终返回这个返回值
    • 返回后通知 (了解)
    • 抛出异常后通知 (了解)
@Pointcut("execution(void com.itheima.dao.BookDao.update())")private void pt(){}@Pointcut("execution(int com.itheima.dao.BookDao.select())")private void pt2(){}//@Before:前置通知,在原始方法运行之前执行
//    @Before("pt()")public void before() {System.out.println("before advice ...");}//@After:后置通知,在原始方法运行之后执行
//    @After("pt2()")public void after() {System.out.println("after advice ...");}//@Around:环绕通知,在原始方法运行的前后执行
//    @Around("pt()")public Object around(ProceedingJoinPoint pjp) throws Throwable {System.out.println("around before advice ...");//表示对原始操作的调用Object ret = pjp.proceed();System.out.println("around after advice ...");return ret;}//    @Around("pt2()")public Object aroundSelect(ProceedingJoinPoint pjp) throws Throwable {System.out.println("around before advice ...");//表示对原始操作的调用Integer ret = (Integer) pjp.proceed();System.out.println("around after advice ...");return ret;}//@AfterReturning:返回后通知,在原始方法执行完毕后运行,且原始方法执行过程中未出现异常现象
//    @AfterReturning("pt2()")public void afterReturning() {System.out.println("afterReturning advice ...");}//@AfterThrowing:抛出异常后通知,在原始方法执行过程中出现异常后运行@AfterThrowing("pt2()")public void afterThrowing() {System.out.println("afterThrowing advice ...");}
}
  • @Around 注意事项
    • 环绕通知必须依赖形参 ProceedingJoinPoint 才能实现对原始方法的调用,进而实现原始方法调用前后同时添加通知
    • 通知中如果未使用 ProceedingJoinPoint 对原始方法进行调用将跳过原始方法的执行
    • 对原始方法的调用可以不接收返回值,通知方法设置成void即可,如果接收返回值,必须设定为Object类型
    • 原始方法的返回值如果是void类型,通知方法的返回值类型可以设置成void,也可以设置成Object
    • 由于无法预知原始方法运行后是否会抛出异常,因此环绕通知方法必须抛出Throwable对象

AOP通知获取数据

获取切入点方法的参数

  • JoinPoint: 适用于前置、后置、返回后、抛出异常后通知
  • JoinPoint 对象描述了连接点方法的运行状态,可以获取到原始方法的调用参数
	@Before("pt()")public void before(JoinPoint jp) {Object[] args = jp.getArgs();System.out.println(Arrays.toString(args));System.out.println("before advice ..." );}
  • ProceedJoinPoint: 适用于环绕通知, 是 JoinPoint 的子类
	@Around("pt()")public Object around(ProceedingJoinPoint pjp) throws Throwable{Object[] args = pjp.getArgs();System.out.println(Arrays.toString(args));ret = pjp.proceed(args);return ret;}

获取切入点方法返回值

  • 返回后通知
    //设置返回后通知获取原始方法的返回值,要求returning属性值必须与方法形参名相同@AfterReturning(value = "pt()",returning = "ret")public void afterReturning(JoinPoint jp, String ret) {System.out.println("afterReturning advice ..."+ret);}
  • 环绕通知 可以手工书写对原始方法的调用,得到的结果即为原始方法的返回值。
	@Around("pt()")public Object around(ProceedingJoinPoint pjp) throws Throwable{ret = pjp.proceed(args);return ret;}

获取切入点方法运行异常信息

  • 抛出异常后通知:可以获取切入点方法中出现的异常信息,使用形参可以接收对应的异常对象
    //设置抛出异常后通知获取原始方法运行时抛出的异常对象,要求throwing属性值必须与方法形参名相同@AfterThrowing(value = "pt()",throwing = "t")public void afterThrowing(Throwable t) {System.out.println("afterThrowing advice ..."+t);}
  • 环绕通知
	@Around("pt()")public Object around(ProceedingJoinPoint pjp) {Object ret = null;try {ret = pjp.proceed(args);} catch (Throwable t) {t.printStackTrace();}return ret;}

百度网盘分享链接输入密码数据错误兼容性处理

@Around("DataAdvice.servicePt()")
public Object trimString(ProceedingJoinPoint pjp) throws Throwable {Object[] args = pjp.getArgs();//对原始参数中的每一个参数进行操作for (int i = 0; i < args.length; i++) {if (args[i].getClass().equals(String.class)) {args[i] = args[i].toString().trim();}}return pjp.proceed(args);
}

这篇关于Spring的另一大的特征:AOP的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/747978

相关文章

Java实现删除文件中的指定内容

《Java实现删除文件中的指定内容》在日常开发中,经常需要对文本文件进行批量处理,其中,删除文件中指定内容是最常见的需求之一,下面我们就来看看如何使用java实现删除文件中的指定内容吧... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细介绍3.1 Ja

springboot项目中整合高德地图的实践

《springboot项目中整合高德地图的实践》:本文主要介绍springboot项目中整合高德地图的实践,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一:高德开放平台的使用二:创建数据库(我是用的是mysql)三:Springboot所需的依赖(根据你的需求再

spring中的ImportSelector接口示例详解

《spring中的ImportSelector接口示例详解》Spring的ImportSelector接口用于动态选择配置类,实现条件化和模块化配置,关键方法selectImports根据注解信息返回... 目录一、核心作用二、关键方法三、扩展功能四、使用示例五、工作原理六、应用场景七、自定义实现Impor

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项

SpringBoot整合Flowable实现工作流的详细流程

《SpringBoot整合Flowable实现工作流的详细流程》Flowable是一个使用Java编写的轻量级业务流程引擎,Flowable流程引擎可用于部署BPMN2.0流程定义,创建这些流程定义的... 目录1、流程引擎介绍2、创建项目3、画流程图4、开发接口4.1 Java 类梳理4.2 查看流程图4

一文详解如何在idea中快速搭建一个Spring Boot项目

《一文详解如何在idea中快速搭建一个SpringBoot项目》IntelliJIDEA作为Java开发者的‌首选IDE‌,深度集成SpringBoot支持,可一键生成项目骨架、智能配置依赖,这篇文... 目录前言1、创建项目名称2、勾选需要的依赖3、在setting中检查maven4、编写数据源5、开启热

Java对异常的认识与异常的处理小结

《Java对异常的认识与异常的处理小结》Java程序在运行时可能出现的错误或非正常情况称为异常,下面给大家介绍Java对异常的认识与异常的处理,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参... 目录一、认识异常与异常类型。二、异常的处理三、总结 一、认识异常与异常类型。(1)简单定义-什么是

SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志

《SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志》在SpringBoot项目中,使用logback-spring.xml配置屏蔽特定路径的日志有两种常用方式,文中的... 目录方案一:基础配置(直接关闭目标路径日志)方案二:结合 Spring Profile 按环境屏蔽关

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.

SpringBoot排查和解决JSON解析错误(400 Bad Request)的方法

《SpringBoot排查和解决JSON解析错误(400BadRequest)的方法》在开发SpringBootRESTfulAPI时,客户端与服务端的数据交互通常使用JSON格式,然而,JSON... 目录问题背景1. 问题描述2. 错误分析解决方案1. 手动重新输入jsON2. 使用工具清理JSON3.