首页 > 其他分享 >【Spring Boot】Spring AOP中的环绕通知

【Spring Boot】Spring AOP中的环绕通知

时间:2024-07-02 18:27:11浏览次数:25  
标签:Spring AOP Boot 切点 切面 通知 注解 执行 方法

目录

一、什么是AOP?

Aspect Oriented Programming(面向切面编程)

AOP是Spring框架的第⼆⼤核⼼(第⼀⼤核⼼是IoC)

AOP是一种思想,是对某一类事情的集中处理。
其中在下面的学习中我们会学习到拦截器、统一异常处理,统一结果处理等,这些都是运用了AOP的统一思想来实现的。

拦截器实现AOP思想作用的维度是前端对后端进行的一次请求和一次响应,主要是检索前端传来的URL,如果检索后返回True,则可以进入Controller开始执行代码,如果返回的为False,则表示失败,直接被拦截在外面,无法执行代码。

统一结果处理则是使用注解@ControllerAdvice(通知类注解),实现ResponseBodyAdvice接口,对响应的结果进行统一处理,对齐进行统一的包装后响应,其中如果数据类型为String类型的话要进行特殊处理,使用ObjectMapper的方法将String格式转为Json格式再次响应。

统一异常处理也是使用注解@ControllerAdvice(通知类注解),以及在方法上使用@ExceptionHandler注解,在全部的程序中如果遇到运行时异常则会自动捕捉,进行抛出,注:编译时异常是写代码过程中出现的,不手动解决就无法运行程序。

接下来我们要学习的是运用了AOP思想,进行AOP的环绕处理

二、AOP 的环绕通知

2.1 切点以及切点表达式

切点=通知类型+切点表达式
切点表示了为该方法提供一组规则,来对程序进行功能增强

通知类型有以下5种:

@Around:环绕通知,此注解标注的通知方法在目标方法前,后都被执行
@Before:前置通知,此注解标注的通知方法在目标方法前被执行
@After:后置通知,此注解标注的通知方法在目标方法后被执行,⽆论是否有异常都会执行
@AfterReturning:返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行
@AfterThrowing:异常后通知,此注解标注的通知方法发⽣异常后执行

如下图所示:
在这里插入图片描述
在该方法上的@Around,表示的是环绕处理,是一种通知类型
其后面的execution(* com.example.demo.controller..(…)) 表示的是该通知类型作用的范围,是切点表达式

2.2 连接点

满足切点表达式规则的方法就是连接点
在这里插入图片描述
在该图中,public recordTime方法就是连接点

2.3 通知(Advice)

通知就是具体要做的内容,简单来说就是方法内执行的代码内容

如图所示:
在这里插入图片描述
该图中标红的位置就是通知内容,在AOP面向切面编程当中,我们把这部分重复的代码逻辑抽取出来单独定义,这部分代码就是通知的内容

2.4 切面(Aspect)

首先使用注解@Aspect来表示该类是一个切面类
然后使用不同的通知类型进行处理,如图表示的是环绕通知类型
在处理过程中ProceedingJoinPoint.proceed()让原始方法执行
在这里插入图片描述
切面(Aspect)=切点(Pointcut)+通知(Advice)
以下代码表示一个完整的切面类:

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Slf4j
@Aspect
@Component

public class TimeAspect {
	/**
	* 记录方法耗时
	*/
	@Around("execution(* com.example.demo.controller.*.*(..))")
	public Object recordTime(ProceedingJoinPoint pjp) throws Throwable {
		//记录方法执行开始时间
		long begin = System.currentTimeMillis();
		
		//执行原始方法
		Object result = pjp.proceed();
		
		//记录方法执行结束时间
		long end = System.currentTimeMillis();
		
		//记录方法执行耗时
		log.info(pjp.getSignature() + "执行耗时: {}ms", end - begin);
		
		return result;
	}
}

2.5 不同通知类型的区别

2.5.1 正常情况下

环绕通知 @Around 标识的通知方法包含两部分,⼀个"前置逻辑",⼀个"后置逻辑".其
中"前置逻辑"会先于 @Before 标识的通知方法执行,"后置逻辑"会晚于 @After 标识的通知方法执行
在这里插入图片描述

2.5.2异常情况下

程序发⽣异常的情况下:
• @AfterReturning 标识的通知方法不会执行, @AfterThrowing 标识的通知方法执行了
• @Around 环绕通知中原始方法调⽤时有异常,通知中的环绕后的代码逻辑也不会在执行了(因为
原始方法调⽤出异常了)
在这里插入图片描述
注意事项:
• @Around 环绕通知需要调⽤ ProceedingJoinPoint.proceed() 来让原始方法执行,其他
通知不需要考虑目标方法执行.
• @Around 环绕通知方法的返回值,必须指定为Object,来接收原始方法的返回值,否则原始方法执
行完毕,是获取不到返回值的.
• ⼀个切面类可以有多个切点

2.6 统一管理切点@PointCut

统一管理切点就是对于复杂的切点表达式进行提取,然后用@PointCut注解方法进行单独声明,再本类下面的程序中如果用到该切点表达式,则直接使用注解后的方法即可,如果在其他类中使用该声明过后的切点表达式则需要使用全路径限定名+该方法即可

本类使用注解后的切点表达式代码如下:

@Slf4j
@Aspect
@Component

public class AspectDemo {

		//定义切点(公共的切点表达式)
		@Pointcut("execution(* com.example.demo.controller.*.*(..))")
		private void pt(){}
		
		//前置通知
		@Before("pt()")
		public void doBefore() {
		//...代码省略
		}
		
		//后置通知
		@After("pt()")
		public void doAfter() {
		//...代码省略
		}
		
		//返回后通知
		@AfterReturning("pt()")
		public void doAfterReturning() {
		//...代码省略
		}
		
		//抛出异常后通知
		@AfterThrowing("pt()")
		public void doAfterThrowing() {
		//...代码省略
		}
		
		//添加环绕通知
		@Around("pt()")
		public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
		//...代码省略
	}
}

在其他类中调用该切点表达式代码如下:

@Slf4j
@Aspect
@Component

	public class AspectDemo2 {
		//前置通知
		@Before("com.example.demo.aspect.AspectDemo.pt()")
		public void doBefore() {
		log.info("执行 AspectDemo2 -> Before 方法");
	}
	
}```

当切点定义使⽤private修饰时,仅能在当前切面类中使⽤,当其他切面类也要使⽤当前切点定义时,就需要把private改为public.引⽤方式为:全限定类名.方法名()
### 2.7     切面优先级@Order
在切面类中会有多个切点同时匹配成功,那么该如何进行执行顺序呢?
应该使用注解@Order(数字)来表示优先级顺序

@Order注解标识的切面类,执行顺序如下:
• @Before 通知:数字越⼩先执行
• @After 通知:数字越⼤先执行

@Order 控制切面的优先级,先执行优先级较⾼的切面,再执行优先级较低的切面,最终执行目标方法.


标签:Spring,AOP,Boot,切点,切面,通知,注解,执行,方法
From: https://blog.csdn.net/smile_sundays/article/details/140105616

相关文章

  • 基于springboot用“异常处理器“捕获解决“数据库信息录入重复“的问题“SQLIntegrity
    前言 当我们编写后端时,会遇到一个问题,那就是:假如A用户向我们的数据库录入完登录信息后(姓名,账号等),B用户同样采用了一个相同的姓名提交了登录信息,那这个时候就不满足username的唯一约束,此时数据库就会报错例如报错如下:Duplicateentry'····'forkey'····'提示......
  • maven构建断网springboot
    maven构建断网springboot我的依赖仓库(本地电脑,记住常用的那几个)org.springframework.boot下的spring-boot-starter-parentspring-boot-starter-web/Users/lin/Documents/repo使用maven进行创建空白项目在pom.xml中补全parent类parent groupId artifactId vers......
  • Bootstrap/布局
    Bootstrap/布局目录Bootstrap/布局断点容器网格列沟槽null断点BreakpointClassinfixDimensionsExtrasmallNone<576pxSmallsm≥576pxMediummd≥768pxLargelg≥992pxExtralargexl≥1200pxExtraextralargexxl≥1400px容器容器可以......
  • SpringBoot3连接Mysql数据库
    pom引入包,启动器<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.o......
  • 怎么彻底关闭Nacos?解决启动时Spring连接Nacos报错
    NacosNacos是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。它是阿里巴巴开源的一个项目,旨在帮助您发现、配置和管理微服务。Nacos提供了一系列丰富的特性集合,支持服务发现和服务健康监测、动态配置服务、服务元数据和流量管理等功能。主要功能服务......
  • Spring Boot 中使用 Spring Security 实现安全访问权限管理:详尽指南
    引言:在现代Web应用开发中,安全是一个至关重要的环节。SpringSecurity是一个功能强大且高度可定制的安全框架,能够为SpringBoot应用提供全面的安全解决方案,包括认证(Authentication)和授权(Authorization)。本文将手把手教你如何在SpringBoot应用中集成SpringSecurity,实现用户登......
  • SpringBoot+mail 轻松实现各类邮件自动推送
    一、简介在实际的项目开发过程中,经常需要用到邮件通知功能。例如,通过邮箱注册,邮箱找回密码,邮箱推送报表等等,实际的应用场景非常的多。早期的时候,为了能实现邮件的自动发送功能,通常会使用JavaMail相关的api来完成。后来Spring推出的JavaMailSender工具,进一步简化了邮件的......
  • 基于SpringBoot+Vue邮件过滤系统设计和实现(源码+LW+调试文档+讲解等)
    ......
  • 开发一套java语言的智能导诊需要什么技术?java+ springboot+ mysql+ IDEA互联网智能3D
    开发一套java语言的智能导诊需要什么技术?java+springboot+mysql+IDEA互联网智能3D导诊系统源码医院导诊系统是一种基于互联网和3D人体的智能化服务系统,旨在为患者提供精准、便捷的医院就诊咨询服务。该系统整合了医院的各种医疗服务资;智慧导诊解决患者盲目就诊问题,减轻分......
  • .js.map文件泄露/Springboot信息泄露
    目录框架识别Webpack简述.js.map文件泄露利用Springboot 很多网站都使用的是现有的框架进行开发的,因此相当于很多目录和文件的路径都是开源可知的,因此我们就可以直接访问对应的路径,如果网站没有进行限制就有可能会导致敏感信息泄露框架识别可以根据页面的报错信息......