SpringAop是什么?

简单介绍:

AOP:Aspect Oriented Programming (面向切面编程、面向方面编程),其实就是面向特定方法编程。

场景:

比如现在有一个需求,我要统计每一个业务方法的耗时时长,

我们只需在业务方法的前面获取一个开始时间,在方法的后面再获取一个结束时间,然后将两时间相减就能得出耗时时长。

这样做当然没问题,但是在一个项目中,业务方法是很多的,如果每次都这样操作,那工作量是非常大的,我们需要换一种方式实现。

我们就可以用到springAop技术

核心:在不惊动原始代码的基础上增强功能。

我们需要统计业务方法的耗时,可以创建一个模板方法,将记录耗时时长的公共的代码放入模板方法。

                                     

原始方法就是业务方法,面向这种特定方法的编程就是面向切面编程。

这个模板方法中定义的逻辑就是创建出来的代理对象方法的逻辑。

实现:

动态代理是面向切面编程最主流的实现。而SpringAOP是Spring框架的高级技术,旨在管理bean对象的过程中,主要通过底层的动态代理机制,对特定的方法进行编程。

编写AOP程序:

针对特定方法根据业务需要进行编程

我们需要创建一个切面类,在类中定义模板方法,并把类交给spring管理

@Component
@Aspect //当前类为切面类
@Slf4j
public class TimeAspect {@Around("execution(* com.itheima.service.*.*(..))") public Object recordTime(ProceedingJoinPoint pjp) throws Throwable {//记录方法执行开始时间long begin = System.currentTimeMillis();//执行原始方法Object result = pjp.proceed();//记录方法执行结束时间long end = System.currentTimeMillis();//计算方法执行耗时log.info(pjp.getSignature()+"执行耗时: {}毫秒",end-begin);return result;}
}

pjp.proceed() 执行原始方法,原始方法可能有返回值,所以最后要把返回值retrun。通过pjp.getSignature() 可以获取原始方法的名称,这样就可以具体知道是哪个方法耗时的时间。

在@Around注解中有个excution表达式,表示对哪些方法进行增强,* com.itheima.service.*.*(..),

* 表示方法的返回值  ,后面的是包名,在任意接口的任意方法上执行。(..)表示方法的形参也是任意的。


AOP核心概念:

①连接点:JointPoint ,可以被AOP控制的方法(暗含方法执行时的相关信息)。

②通知:Advice,指那些重复的逻辑,也就是共性功能(最终体现为一个方法)。

③切入点:PointCut,匹配连接点的条件,通知仅会在切入点方法执行时被应用。

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

⑤目标对象:Target,通知所应用的对象

AOP执行流程:

定义好切入点表达式后,在程序运行时,SpringAOP会自动地基于动态代理技术为目标对象生成一个对应的代理对象,也就是上图的DeptServiceProxy对象, 在对象中已经做了对业务方法的增强。此时,再进行service注入的时候,spring就不会注入原始的目标对象,而是注入生成出来的代理对象,此代理对象已经对业务方法做了增强的处理。


AOP进阶:
Spring中AOP的通知类型:
  • @Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行

  • @Before:前置通知,此注解标注的通知方法在目标方法前被执行

  • @After :后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行

  • @AfterReturning : 返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行

  • @AfterThrowing : 异常后通知,此注解标注的通知方法发生异常后执行

注意:

① :@Around环绕通知需要自己调用ProceedingJoinPoint.proceed() 来让原始方法执行,其它通知不需要考虑目标方法执行。

②:@Aound环绕通知方法的返回值,必须指定为Object,来接收原始方法的返回值。

五种通知类型代码演示:
@Slf4j
@Component
@Aspect
public class MyAspect1 {//切入点方法(公共的切入点表达式)@Pointcut("execution(* com.itheima.service.*.*(..))")private void pt(){}//前置通知(引用切入点)@Before("pt()")public void before(JoinPoint joinPoint){log.info("before ...");}//环绕通知@Around("pt()")public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {log.info("around before ...");//调用目标对象的原始方法执行Object result = proceedingJoinPoint.proceed();//原始方法在执行时:发生异常//后续代码不在执行log.info("around after ...");return result;}//后置通知@After("pt()")public void after(JoinPoint joinPoint){log.info("after ...");}//返回后通知(程序在正常执行的情况下,会执行的后置通知)@AfterReturning("pt()")public void afterReturning(JoinPoint joinPoint){log.info("afterReturning ...");}//异常通知(程序在出现异常的情况下,执行的后置通知)@AfterThrowing("pt()")public void afterThrowing(JoinPoint joinPoint){log.info("afterThrowing ...");}
}

通知顺序:

默认按照切面类的类名字母排序:

  • 目标方法前的通知方法:字母排名靠前的先执行

  • 目标方法后的通知方法:字母排名靠前的后执行

一般我们通过@Order注解可以控制通知的执行顺序

@Slf4j
@Component
@Aspect
@Order(2)  //切面类的执行顺序(前置通知:数字越小先执行; 后置通知:数字越小越后执行)
public class MyAspect2 {//前置通知@Before("execution(* com.itheima.service.*.*(..))")public void before(){log.info("MyAspect2 -> before ...");}//后置通知 @After("execution(* com.itheima.service.*.*(..))")public void after(){log.info("MyAspect2 -> after ...");}
}
切入点表达式:

作用:主要用来决定项目中的哪些方法需要加入通知。

它的常见形式有两种:

①execution(……):

根据方法的签名来匹配

execution(访问修饰符?  返回值  包名.类名.?方法名(方法参数) throws 异常?)

其中带?的表示可以省略的部分

  • 访问修饰符:可省略(比如: public、protected)

  • 包名.类名: 可省略

  • throws 异常:可省略(注意是方法上声明抛出的异常,不是实际抛出的异常)

示例:

@Before("execution(void com.itheima.service.impl.DeptServiceImpl.delete(java.lang.Integer))")

②@annotation(……) :

根据注解匹配

自定义注解:Log           一般我们记录操作日志需要用到  自定义注解 + 环绕通知

//自定义注解
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {public String title() ;								// 模块名称public OperatorType operatorType() default OperatorType.MANAGE;	// 操作人类别public int businessType() ;     // 业务类型(0其它 1新增 2修改 3删除)public boolean isSaveRequestData() default true;   // 是否保存请求的参数public boolean isSaveResponseData() default true;  // 是否保存响应的参数
}@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import(value = LogAspect.class)            // 通过Import注解导入日志切面类到Spring容器中
public @interface EnableLogAspect {  //这个注解可以添加到启动类上,程序启动时可以扫描到LogAspect这个切面类
}@Aspect
@Component
@Slf4j
public class LogAspect {   //环绕通知切面类定义@Autowiredprivate AsyncOperLogService asyncOperLogService;@Around("@annotation(sysLog)")public Object doAroundAdvice(ProceedingJoinPoint joinPoint, Log sysLog){// 构建前置参数SysOperLog sysOperLog = new SysOperLog() ;LogUtil.beforeHandleLog(sysLog, joinPoint, sysOperLog);  //封装日志信息Object proceed = null;try {proceed = joinPoint.proceed();              // 执行业务方法LogUtil.afterHandlLog(sysLog,proceed, sysOperLog, 0, null);   //封装日志信息} catch (Throwable e) {      // 代码执行进入到catch中,业务方法执行产生异常e.printStackTrace();LogUtil.afterHandlLog(sysLog,proceed, sysOperLog, 1, e.getMessage()); //封装日志信息throw new RuntimeException();}// 保存日志数据asyncOperLogService.saveSysOperLog(sysOperLog);return proceed ;}
}

连接点:

在Spring中用JoinPoint抽象了连接点,用它可以获得方法执行时的相关信息,如目标类名、方法名、方法参数等。

  • 对于@Around通知,获取连接点信息只能使用ProceedingJoinPoint类型

  • 对于其他四种通知,获取连接点信息只能使用JoinPoint,它是ProceedingJoinPoint的父类型

@Slf4j
@Component
@Aspect
public class MyAspect7 {@Pointcut("@annotation(com.itheima.anno.MyLog)")private void pt(){}//前置通知@Before("pt()")public void before(JoinPoint joinPoint){log.info(joinPoint.getSignature().getName() + " MyAspect7 -> before ...");}//后置通知@Before("pt()")public void after(JoinPoint joinPoint){log.info(joinPoint.getSignature().getName() + " MyAspect7 -> after ...");}//环绕通知@Around("pt()")public Object around(ProceedingJoinPoint pjp) throws Throwable {//获取目标类名String name = pjp.getTarget().getClass().getName();log.info("目标类名:{}",name);//目标方法名String methodName = pjp.getSignature().getName();log.info("目标方法名:{}",methodName);//获取方法执行时需要的参数Object[] args = pjp.getArgs();log.info("目标方法参数:{}", Arrays.toString(args));//执行原始方法Object returnValue = pjp.proceed();return returnValue;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/479984.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

算法通关村-----继续看回溯问题

复原IP地址 问题描述 有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 ‘.’ 分隔。 例如:“0.1.2.201” 和 “192.168.1.1” 是 有效 IP 地址,但是 “0.011.…

MAC端Terminus 绿色版下载【一键安装,即可使用】

Termius Mac 是一款非常好用而且漂亮的SSH客户端,能快速远程控制服务器 现在呢,很多小伙伴,都开始使用这个软件啦 但是对于mac系统来说: 这个软件不要在苹果app store下载,不能实现传输功能这个软件目前有7天适用期&a…

MybatisPlus多表联查-分页关联查询+根据id获取多表联查后的单行数据

分页关联查询 需求分析 有两张表w以及d,需要w的一些字段以及d的一些字段在前端显示 此时就需要用到关联查询,查询到的数据放入视图类,显示在前端 项目结构 视图类 package com.wedu.modules.tain.entity.vo;import lombok.Data;import ja…

SpringBoot常见问题

1 引言 Spring Boot是一个基于Spring框架的快速开发脚手架,它简化了Spring应用的初始化和搭建过程,提供了众多便利的功能和特性,比如自动配置、嵌入式Tomcat等,让开发人员可以更加专注于业务逻辑的实现。   Spring Boot还提供了…

Linux:Jenkins:GitLab+Maven+Jenkins的部署(1)

1.环境 我这里准备了三台centos7 1.用于部署gitlab 运行内存:6G 名字:Jenkins-GitLab 192.168.6.1 2.用于部署jenkins 运行内存:2G 名字:Jenkins-server 192.168.6.2 3.用于打包测试…

你真的懂串口通信吗?

一、什么是串口通讯? 串行通讯是指仅用一根接收线和一根发送线就能将数据以位进行传输的一种通讯方式。尽管串行通讯的比按字节传输的并行通信慢,但是串口可以在仅仅使用两根线的情况下就能实现数据的传输。 典型的串口通信使用3根线完成,分…

网络安全--网鼎杯2018漏洞复现(二次注入)

一、环境:在线测试平台 BUUCTF在线评测 (buuoj.cn) 二、进入界面先尝试万能账号 1or11# 换格式 hais1bux1 11or11# 三、万能的不行那我们就得想注册了,去register.php去看看 注册个账号 发现用户名回显,猜测考点为用户名处二次注入&…

《戴森球计划》好玩吗?《戴森球计划》怎么在苹果电脑上安装 戴森球计划攻略 Mac游戏推荐

《戴森球计划》是一款具有强大现实科学基础的模拟策略游戏,玩家的目标是构建能源效率极高的戴森球以解决能源问题。游戏的背景设定启发于科幻作品中的戴森球概念。游戏采用逼真的物理模拟,玩家需要合理规划资源,以应对复杂的能源危机。那么《…

Open3D三维重建

原始点云: alpha_shape算法 import open3d as o3dpcd o3d.io.read_point_cloud("airplane_0001.pcd") mesh o3d.geometry.TriangleMesh.create_from_point_cloud_alpha_shape(pcd, alpha0.1) o3d.visualization.draw_geometries([mesh], mesh_show_b…

【贪心算法】代码随想录算法训练营第三十七天 |738.单调递增的数字,968.监控二叉树,总结(待补充)

738.单调递增的数字 1、题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 2、文章讲解:代码随想录 3、题目: 给定一个非负整数 N,找出小于或等于 N 的最大的整数,同时这个整数需要…

微信小程序之会议OA个人中心后台交互

目录 获取用户昵称头像和昵称 小程序登录 登录-小程序 wx.checkSession wx.login wx.request 后台 准备数据表 反向生成工具生成 准备封装前端传过来的数据 小程序服器配置 导入微信小程序SDK application.yml WxProperties WxConfig WxAuthController 登录-小…

Sora:新一代实时音视频通信框架

一、Sora简介 Sora是一个开源的实时音视频通信框架,旨在提供高效、稳定、可扩展的音视频通信解决方案。它基于WebRTC技术,支持跨平台、跨浏览器的实时音视频通信,并且具备低延迟、高并发、易集成等特点。 --点击进入Sora(一定要科学哦&#x…