Spring学习04-[Spring容器核心技术AOP学习]

AOP学习

  • AOP介绍
  • 使用
    • 对业务方法添加计算时间的增强
  • @EnableAspectJAutoProxy
  • AOP的术语
  • 通知
    • 前置通知@Before
    • 后置通知@After
    • 返回通知@AfterReturning
    • 异常通知@AfterThrowing
    • 总结-通知执行顺序
  • 切点表达式的提取-使用@Pointcut进行抽取
  • 切点表达式的详细用法
    • execution和@annotation组合
  • SpringAOP和注解的使用-配置全局日志

AOP介绍

在这里插入图片描述
在这里插入图片描述

  • 如何在Spring中创建一个所谓切面?
    @Aspect+@Component+通知+切点
  • 切面里面的代码怎么运行在业务方法(之前、之后)?
    通知+切点

使用

实现一个对service方法的增强,添加日志

  • 添加依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>

在这里插入图片描述

对业务方法添加计算时间的增强

  • 业务类
@Service
public class UserService {public void add(){System.out.println("增加");}public void delete(){System.out.println("删除");}public void update(){System.out.println("修改");}public void query(){System.out.println("查询");}
}
  • 切面类
    啥叫面向切面编程:面向切面编程就是面向切面类进行编程
@Aspect //标记为切面类
@Component
public class LogAspect {//实现方法用时 切点表达式@Around("execution(* com.sping.service.UserService.*(..))")public Object log(ProceedingJoinPoint joinPoint) throws Throwable {//记录方法用时long startTime = System.currentTimeMillis();//执行具体的方法try {joinPoint.proceed(); //连接点就是具体的方法}catch (Exception e){System.out.println("方法执行异常");throw new Exception();}long endTime = System.currentTimeMillis();System.out.println("方法用时:" + (endTime - startTime) + "ms");return null;}}
  • 测试
  @Autowiredprivate UserService userService;@Testpublic void test() throws InterruptedException {userService.add();}

在这里插入图片描述

@EnableAspectJAutoProxy

在这里插入图片描述
在这里插入图片描述

AOP的术语

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
切面、切点、通知、连接点;顾问(通知+切点)
在这里插入图片描述

通知

  • 前置通知
  • 后置通知
  • 返回通知
  • 异常通知
    在定义切点的时候,可以把切点定义到另一个方法中,然后在通知中引入即可
@Aspect
@Component
public class LogAspect{@Pointcut("execution( * com.sping.service.UserService.*(..))")public void PointCut(){}@AfterReturning("PointCut()")public void log(){System.out.println("后置通知执行");}
}

环绕通知和其他通知的区别:环绕通知需要手动去拿到连接点执行目标方法,环绕方法更加的灵活

前置通知@Before

在目标方法执行之前执行

@Aspect
@Component
public class LogAspect{@Before("execution(* com.sping.service.*.*(..))")public void log(){System.out.println("前置通知执行");}
}

可以看到标注了前置通知后,前置通知的增强方法先执行,然后再执行目标方法
在这里插入图片描述

后置通知@After

与前置通知相反,后置通知是目标方法执行之后才会执行,通知里的增强方法

@Aspect
@Component
public class LogAspect{@After("execution(* com.sping.service.*.*(..))")public void log(){System.out.println("后置通知执行");}
}

在这里插入图片描述

返回通知@AfterReturning

执行位置:在方法执行完,返回值返回之前执行

    @Pointcut("execution( * com.sping.service.UserService.*(..))")public void PointCut(){}/*** 返回通知* 1、可以获取返回值* 2、在后置通知之前执行* 3、方法执行返回值需要手动声明*/@AfterReturning(value = "PointCut()",returning = "returnValue")public void log(){System.out.println("返回通知执行,返回值:" + returnValue);}

在这里插入图片描述

异常通知@AfterThrowing

   /*** 发生了异常后会执行*/@AfterThrowing(value = "PointCut()",throwing = "exception")public void log(Exception exception){System.out.println("异常通知执行" + exception.getMessage());}

在这里插入图片描述

总结-通知执行顺序

正常:前置通知---->目标方法---->返回通知---->后置通知(finallly)
异常:前置通知---->目标方法---->异常通知---->后置通知(finally)
在这里插入图片描述

切点表达式的提取-使用@Pointcut进行抽取

方便切点进行统一管理

  @Pointcut("execution( * com.sping.service.UserService.*(..))")public void PointCut(){}

切点表达式的详细用法

  • 切点标识符
  • execution:用于匹配方法执行连接点。这是使用SpringAOP时,使用的主要切点标识符,可以匹配到方法级别,细粒度
    在这里插入图片描述
  • @annotation:限制匹配连接点,在Spring AOP中执行的具有给定的注解(只有含有某些注解,才会生效)
    比如下面这段代码,只有我方法上加了@Log注解的才会被切到,进行增强
   @Pointcut("@annotation(com.sping.annotation.Log)")public void PointCut(){}

execution和@annotation组合

格式:@Pointcut(“execution()&&”+“@annotation()”)

  • 第一种方式:
     @Pointcut("execution(* com.sping.service.*.*(..))&&"+"@annotation(com.sping.annotation.Log)")public void PointCut() {}@Before(value = "PointCut()")public void log() {System.out.println("开始记录日志");}
  • 第二种方式:
    设置两个切点方法,再引入的时候通过&&符号进行引入
   @Pointcut("execution(* com.sping.service.*.*(..))")public void pointCutClass() {}@Pointcut("@annotation(com.sping.annotation.Log)")public void pointCutAnnotation(){}@Before(value = "pointCutClass()&&pointCutAnnotation()")public void log() {System.out.println("开始记录日志");}

SpringAOP和注解的使用-配置全局日志

  • 自定义注解
package com.test.aspect;import java.lang.annotation.*;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {/*模块*/String title() default "";/*功能*/String action() default "";
}
  • 切面类
/*** @ClassName LogAspect* @Description* @Author 周志强* @Date 2021/5/12 12:27* @Version 1.0*/
@Aspect
@Component("logAspect")
public class LogAspect {private static Logger log= LoggerFactory.getLogger(LogAspect.class);//配置切入点@Pointcut("@annotation(com.test.aspect.Log)")public void logPointCut(){}//后置通知 用于拦截操作,在方法返回后执行@AfterReturning(pointcut = "logPointCut()")public void doBefore(JoinPoint joinPoint){handelLog(joinPoint,null);}//拦截异常操作,有异常时执行@AfterThrowing(value = "logPointCut()",throwing = "e")public void doAfter(JoinPoint joinPoint,Exception e){handelLog(joinPoint,e);}public void handelLog(JoinPoint joinpoint,Exception e){try {Log annotationLog = getAnnotationLog(joinPoint);if (annotationLog == null) {return;}String className = joinPoint.getTarget().getClass().getName();String methodName = joinPoint.getSignature().getName();String action = annotationLog.action();String title = annotationLog.title();//打印日志,如有需要还可以存入数据库logger.info(">>>>>>>>>>>>>模块名称:{}",title);logger.info(">>>>>>>>>>>>>操作名称:{}",action);logger.info(">>>>>>>>>>>>>类名:{}",className);logger.info(">>>>>>>>>>>>>方法名:{}",methodName);}catch (Exception exception){logger.error("=前置通知异常=");logger.error("异常信息:{}",e.getMessage());e.printStackTrace();}}private static Log getAnnotationLog(JoinPoint joinPoint) throws Exception {Signature signature = joinPoint.getSignature();MethodSignature methodSignature= (MethodSignature) signature;Method method = methodSignature.getMethod();if (method != null) {return  method.getAnnotation(Log.class);}return null;}
}

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

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

相关文章

STM32快速搭建项目框架

注&#xff1a;编写本博客的原因&#xff0c;学习期间基于复习之前知识点的需要&#xff0c;故撰写本教程&#xff0c;即是复习前面的知识点也是作为博客的补充 1.0 文件夹的创建 创建一个STM32项目为模版工程&#xff0c;问价夹下分别包含4个子文件夹&#xff0c;一个是Librar…

Java 使用POI 读取Excel 中的全部图片,非嵌入式图片

示例代码 excel文件格式 : xlsx public static Map<String, XSSFPictureData> getPictures(Sheet sheet) throws Exception {Map<String, XSSFPictureData> pictures new HashMap<>();// 对于XLSX文件if (sheet instanceof XSSFSheet) {XSSFDrawing drawin…

嘉立创EDA学习笔记

嘉立创EDA学习笔记 PCB引线一、设计规则间距安全间距其他间距 物理导线网络长度差分对过孔尺寸 平面铺铜 PCB布线 作为一个嵌入式开发潜力工程师&#xff0c;咱们必须得学会如何绘制开发板以满足顾客各种功能的需求&#xff0c;因此小编去学习了一下嘉立创&#xff0c;写这篇文…

VSCode用ssh连接ubuntu虚拟机实现远程访问文件夹

1. ubuntu安装ssh服务 1.1 安装 sudo apt-get install ssh sudo apt-get install openssh-server1.2 启动ssh服务 sudo service ssh start sudo service ssh status # 查看状态 ## 或者用下面方式重启ssh服务 ## /etc/init.d/ssh restart1.3 ssh服务加入开机启动 sudo syst…

C++实现对结构体信息排序

思路解读&#xff1a; 定义结构体 Student: 结构体 Student 用来表示学生信息&#xff0c;包含两个成员变量&#xff1a;name&#xff08;学生姓名&#xff09;和 score&#xff08;学生分数&#xff09;。Student 结构体定义了一个构造函数&#xff0c;用于初始化 name 和 sco…

代码随想录算法训练营第7天

454.四数相加 题目链接&#xff1a;454. 四数相加 II - 力扣&#xff08;LeetCode&#xff09; 视频/文档链接&#xff1a;代码随想录 (programmercarl.com) 第一想法 遍历数组num1,num2&#xff0c;计算其和出现的数量&#xff0c;放入map集合中&#xff0c;键为和&#xff0…

HTML语言常见标签

语法 HEAD部分的HTML标签 1 标题标签 <title>标题内容</title> 2 段落标签 <meta charset"utf-8"/> BODY部分的HTML标签 1标题标签&#xff08;独占一行&#xff09;<h1>标题内容</h1> 2段落标签&#xff08;独占一行&#xff09;…

大模型一些概念的理解 - 线性层、前向传播、后向传播

文章目录 前言一、线性层1. 什么是线性层&#xff1f;2. 通俗解释3. 示例 二、前向传播1. 什么是前向传播&#xff1f;2. 通俗解释3. 示例 三、后向传播1. 什么是后向传播&#xff1f;2. 通俗解释3. 具体步骤 四、示例五、在 PyTorch 中的后向传播 前言 最近提问里有问到一些名…

TK 检查输入框是否为空

在Python的Tkinter库中&#xff0c;你可以使用事件绑定或者在按钮点击事件中检查输入框的值是否为空来实现这个功能。以下是一个简单的例子&#xff1a; import tkinter as tk from tkinter import messageboxdef check_input():entry input_box.get()if not entry:messagebo…

TLP152 光耦合器:工程师的可靠选择

东芝的 TLP152 光耦合器是一款稳健且多功能的组件&#xff0c;能够满足各种高速和高可靠性应用中的工程师需求。本文将深入探讨 TLP152 的技术特性、优点和应用&#xff0c;突出其在市场中的独特性。 主要特点和规格 TLP152 光耦合器集成了一颗铝镓砷&#xff08;GaAlAs&…

C#字符串操作:判断一个字符串按特定字符分割后的子字符串是否有重复的几种常用方法

C#判断一个字符串按特定字符分割后的子字符串是否有重复的几种常用方法&#xff1a; 方法一&#xff1a;使用 LINQ 你可以使用 LINQ 来简化检查重复子字符串的过程&#xff1a; using System; using System.Linq;class Program {static void Main(){string input "CCT…

昇思14天

ResNet50图像分类 1. ResNet50图像分类概述 ResNet50是一种用于图像分类的深度卷积神经网络。图像分类是计算机视觉的基本应用&#xff0c;属于有监督学习范畴。ResNet50通过引入残差结构&#xff0c;解决了深层网络中的退化问题&#xff0c;使得可以训练非常深的网络。 2. …

了解Adam和RMSprop优化算法

优化算法是机器学习和深度学习模型训练中至关重要的部分。本文将详细介绍Adam&#xff08;Adaptive Moment Estimation&#xff09;和RMSprop&#xff08;Root Mean Square Propagation&#xff09;这两种常用的优化算法&#xff0c;包括它们的原理、公式和具体代码示例。 RMS…

大模型/NLP/算法面试题总结4——bert参数量计算

BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;是一种基于Transformer结构的预训练语言表示模型&#xff0c;它在自然语言处理&#xff08;NLP&#xff09;领域取得了显著的效果。计算BERT模型的参数量主要涉及到其Transformer层中的各…

配置路由器支持Telnet操作 计网实验

实验要求&#xff1a; 假设某学校的网络管理员第一次在设备机房对路由器进行了初次配置后&#xff0c;他希望以后在办公室或出差时也可以对设备进行远程管理&#xff0c;现要在路由器上做适当配置&#xff0c;使他可以实现这一愿望。 本实验以一台R2624路由器为例&#xff0c;…

OpenCV MEI相机模型(全向模型)

文章目录 一、简介二、实现代码三、实现效果参考文献一、简介 对于针孔相机模型,由于硬件上的限制(如进光量等),他的视野夹角往往有效区域只有140度左右,因此就有研究人员为每个针孔相机前面再添加一个镜片,如下所示: 通过折射的方式增加了相机成像的视野,虽然仍然达不…

认识同源策略

同源策略是一种浏览器安全机制&#xff0c;用于限制一个源的文档或脚本如何与另一个源的资源进行交互。源由协议&#xff08;如HTTP或HTTPS&#xff09;、域名和端口号组成。如果两个URL的协议、域名和端口都相同&#xff0c;则它们具有相同的源。 同源策略主要影响以下几个方…

东方通Tongweb发布vue前端

一、前端包中添加文件 1、解压vue打包文件 以dist.zip为例&#xff0c;解压之后得到dist文件夹&#xff0c;进入dist文件夹&#xff0c;新建WEB-INF文件夹&#xff0c;进入WEB-INF文件夹&#xff0c;新建web.xml文件&#xff0c; 打开web.xml文件&#xff0c;输入以下内容 …

理解局域网技术:从基础到进阶

局域网&#xff08;LAN&#xff09;是在20世纪70年代末发展起来的&#xff0c;起初主要用于连接单位内部的计算机&#xff0c;使它们能够方便地共享各种硬件、软件和数据资源。局域网的主要特点是网络为一个单位所拥有&#xff0c;地理范围和站点数目均有限。 局域网技术在计算…

RequestContextHolder多线程获取不到request对象

RequestContextHolder多线程获取不到request对象&#xff0c;调用feign接口时&#xff0c;在Feign中的RequestInterceptor也获取不到HttpServletRequest问题解决方案。 1.RequestContextHolder多线程获取不到request对象 异常信息&#xff0c;报错如下&#xff1a; 2024-07-0…