Spring-AOP

Springboot AOP 拦截 直接返回结果数据 阅读详情

笔记源自黑马程序员2022新版SSM框架教程

AOP简介

基础概念

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

作用:在不惊动原始设计的基础上为其功能进行增强

核心概念

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

  • 在SpringAOP中理解为方法的执行

切入点(Pointcut):匹配连接点的式子

  • 在SpringAOP中,一个切入点可以只描述一个具体方法,也可以匹配多个方法

通知(Advice):在切入点执行的操作,也就是共性功能

  • 在SpringAOP中,功能最终以方法的形式呈现

通知类:定义通知的类

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

AOP入门实例

需要的依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.23</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>

定义切片类

@Component
@Aspect
public class MyAdvice {

  @Pointcut("execution(void com.Learning2.service.UserService.test())")
  private void pointCut(){}

  @Before("pointCut()")
  public void before(){
    System.out.println("测试。。");
  }
}

切入点定义依托一个不具有实际意义的方法进行,即无参数,无返回值,方法体无实际逻辑

@Pointcut("execution(void com.Learning2.service.UserService.test())")
private void pointCut(){}

绑定切入点与通知关系,并指定通知添加到原始连接点的具体执行位置

@Before("pointCut()")

定义通知类受Spring容器管理,并定义当前类为切片类

@Component
@Aspect

开启Spring对AOP注解驱动的支持

在SpringConfig类中加上@EnableAspectJAutoProxy注解

AOP工作流程

工作流程

  • 1.Spring容器启动
  • 2.读取所有切面配置中的切入点
@Before("pointCut()")
  • 3.初始化Bean,判定Bean对应的类中的方法是否匹配到任意切入点
    • 匹配失败,创建对象
    • 匹配成功,创建原始对象(目标对象)的代理对象
  • 4.获取Bean执行方法
    • 获取Bean,调用方法并执行,完成操作
    • 获取的Bean是代理对象,根据代理对象的运行模式运行原始方法以及增强内容,完成操作

核心概念

  • 目标对象(Target)

原始功能去掉共性功能对应的类产生的对象,这种对象是无法直接完成最终工作的

  • 代理(Proxy)

目标对象无法直接完成工作,需要对其进行功能回填,通过原始对象的代理对象实现

SpringAOP本质

  • 代理模式

AOP切入点表达式

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

切入点表达式的标准格式

动作关键字(访问修饰符 返回值 包名.类/接口名.方法名(参数) 异常名)

  • 动作关键字:描述切入点的行为动作,例如execution表示执行到指定切入点
  • 访问修饰符:public,private等,默认public
  • 返回值
  • 包名
  • 类/接口名
  • 方法名
  • 参数
  • 异常名:方法定义中抛出指定异常,可以省略

通配符

可以使用通配符描述切入点,快速描述

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

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

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

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

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

书写技巧

  • 所有代码按照标准格式开发,否则以下技巧全部失效
  • 描述切入点通常描述接口,而不描述实现类
  • 访问控制修饰符针对接口开发均采用public描述(可省略访问控制修饰符描述)
  • 返回值类型对于增删改类使用精准类型加速匹配,对于查询类使用*统配快速描述
  • 包名书写尽量不使用…匹配,效率过低,常用*做单个包描述匹配,或精准匹配
  • 接口名/类名书写名称与模块相关的采用*匹配,例如UserService书写成*Service,绑定业务层接口名
  • 方法名书写以动词进行精准匹配,名词采用*匹配,例如getByID书写成getBy*,selectAll书写成selectAll
  • 参数规则较为复杂,根据业务方法灵活调整
  • 通常不使用异常作为匹配规则

AOP通知类型

  • AOP通知描述了抽取的共性功能,根据共性功能抽取的位置不同,最终运行代码时要将其加入到合理的位置
  • AOP通知共分为5种类型
    • 前置通知
    • 后置通知
    • 环绕通知(重点)
    • 返回后通知(了解)
    • 抛出异常后通知(了解)

前置通知

  • 名称:@Before
  • 类型:方法注解
  • 位置:通知方法定义上方
  • 作用:设置当前通知方法与切入点之前的绑定关系,当前通知方法在原始切入点方法前运行
  • 范例:
  @Before("pointCut()")
  public void before(){
    System.out.println("运行前");
  }
  • 相关属性:value(默认):切入点方法名,格式为类名.方法名(),如果在同一个类中,类名可省略

后置通知

  • 名称:@After
  • 类型:方法注解
  • 位置:通知方法定义上方
  • 作用:设置当前通知方法与切入点之前的绑定关系,当前通知方法在原始切入点方法后运行
  • 范例:
  @After("pointCut()")
  public void after(){
    System.out.println("运行后");
  }
  • 相关属性:value(默认):切入点方法名,格式为类名.方法名(),如果在同一个类中,类名可省略

环绕通知

  • 名称:@Around
  • 类型:方法注解
  • 位置:通知方法定义上方
  • 作用:设置当前通知方法与切入点之前的绑定关系,当前通知方法在原始切入点方法前后运行
  • 范例:
  @Around("pointCut()")
  public Object around(ProceedingJoinPoint pjp) throws Throwable{
    System.out.println("运行前");
    Object ret = pjp.proceed();
    System.out.println("运行后");
    return ret;
  }
  • @Around注意事项
    • 1.环绕通知必须依赖参数ProceedingJoinPoint才能实现对原始方法的调用,进而实现原始方法调用前后同时添加通知
    • 2.通知中如果未使用ProceedingJoinPoint对原始方法进行调用将跳过原始方法的执行
    • 3.对原始方法的调用可以不接受返回值,通知方法设置成void即可,如果接受返回值,必须设定为Object类型
    • 4.原始方法的返回值如果是void类型,通知方法的返回值类型可以设置成void,也可以设置成Object
    • 5.由于无法预知原始方法运行后是否会抛出异常,因此环绕通知方法必须抛出Throwable对象

返回后通知(了解)

  • 名称:@After
  • 类型:方法注解
  • 位置:通知方法定义上方
  • 作用:设置当前通知方法与切入点之前的绑定关系,当前通知方法在正常执行完毕后运行
  • 范例:
  @AfterReturning("pointCut()")
  public void afterReturning(){
    System.out.println("运行完毕后");
  }
  • 相关属性:value(默认):切入点方法名,格式为类名.方法名(),如果在同一个类中,类名可省略

抛出异常后通知(了解)

  • 名称:@AfterThrowing
  • 类型:方法注解
  • 位置:通知方法定义上方
  • 作用:设置当前通知方法与切入点之前的绑定关系,当前通知方法在原始切入点方法运行抛出异常后执行
  • 范例:
  @AfterThrowing("pointCut()")
  public void afterThrowing(){
    System.out.println("运行抛出异常后");
  }
  • 相关属性:value(默认):切入点方法名,格式为类名.方法名(),如果在同一个类中,类名可省略

案例测试

测试Service类中的方法的运行时间

@Component
@Aspect
public class MyAdvice {

  //service包下的所有以Service为后缀的类的所有方法
  @Pointcut("execution(* com.Learning2.service.*Service.*(..))")
  private void pointCut(){}

  @Around("pointCut()")
  public Object around(ProceedingJoinPoint pjp) throws Throwable{
    //代表了一次执行的签名信息,封装了这一次的执行过程
    Signature signature = pjp.getSignature();
    String className = signature.getDeclaringTypeName();
    String method = signature.getName();

    long start = System.currentTimeMillis();
    Object ret = pjp.proceed();
    long end = System.currentTimeMillis();
    System.out.println("执行时间:"+className+"."+method+"---->"+(end-start)+"ms");
    return ret;
  }
}

测试类

public class App {

  public static void main(String[] args) {
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);

    UserService userService = applicationContext.getBean(UserService.class);

    userService.test();
    userService.findAll();
  }
}

运行结果

This is Service
执行时间:com.Learning2.service.UserService.test---->0ms
十月 02, 2022 3:56:30 下午 com.alibaba.druid.support.logging.JakartaCommonsLoggingImpl info
信息: {dataSource-1} inited
执行时间:com.Learning2.service.UserService.findAll---->2397ms

Process finished with exit code 0

AOP通知获取数据

获取切入点方法的参数

  • JoinPoint:适用于前置、后置、返回后、抛出异常后通知
  • ProceedingJoinPoint:适用于环绕通知

JoinPoint对象描述了连接点方法的运行状态,可以获取到原始方法的调用参数

  @Before("pointCut()")
  public void before(JoinPoint jp){
    Object[] args = jp.getArgs();
    System.out.println(Arrays.toString(args));
  }

ProceedingJoinPoint是JoinPoint的子类

  @Around("pointCut()")
  public Object around(ProceedingJoinPoint pjp) throws Throwable{
    Object[] args = pjp.getArgs();
    System.out.println(Arrays.toString(args));
    Object ret = pjp.proceed();
    return ret;
  }

获取切入点方法返回值

  • 返回后通知
  • 环绕通知

返回后通知可以获取切入点方法中的返回信息,使用形参可以接受对应的返回值

  @AfterReturning(value = "pointCut()",returning = "ret")
  public void afterReturning(Object ret){
    System.out.println("afterReturning ..."+ret);
  }

环绕通知中可以手工书写对原始方法的调用,得到的结果即为原始方法的返回值

  @Around("pointCut()")
  public Object around(ProceedingJoinPoint pjp) throws Throwable{
    Object ret = pjp.proceed();
    return ret;
  }

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

  • 抛出异常后通知
  • 环绕通知

抛出异常后通知可以获取切入点方法中出现的异常信息,使用形参可以接受对应的异常对象

  @AfterThrowing(value = "pointCut()",throwing = "throwable")
  public void afterThrowing(Throwable throwable){
    System.out.println("afterThrowing..."+throwable);
  }

在环绕通知中可以直接用try catch来接收异常

  @Around("pointCut()")
  public Object around(ProceedingJoinPoint pjp){
    Object ret = null;
    try {
      ret = pjp.proceed();
    } catch (Throwable e) {
      e.printStackTrace();
    }
    return ret;
  }

欢迎访问我的个人网站

Haystack框架实战:从零构建企业级智能问答系统 自然语言处理(NLP)技术通过让计算机理解和生成人类语言,正在深刻改变信息检索与交互方式。其核心原理在于将文本转化为机器可处理的向量表示,并通过语义相似度计算实现精准匹配。这一技术价值在于能够从海量非结构化数据中快速提取精准信息,大幅提升知识获取效率。在工程实践中,检索增强生成(RAG)架构结合了密集向量检索与大语言模型生成能力,成为构建智能问答、知识库助手等应用的主流方案。该架构通过将用户查询与文档库进行语义匹配,并为大语言模型提供精准上下文,有效提升了回答的准确性与可追溯性。本文以Haystack这一生 阅读详情

相关推荐

骗分导论 CSP、NOIP、蓝桥杯、PAT、USACO等竞赛的算法骗分技巧 轻松省三

问题来了,那么多座桥,炸一座就破坏岛屿的联系,可能性微乎其微(除非特别设计数据)。它们的价值极大,不仅能初步帮你检验程序的对错,而且,如果你不会做这道题,你就可以直接输出样例!在OI考试中最后难的题数据最后的几个,他们往往不会创造新的数据,此时就可以直接输出最后几个数据了。需要运用《骗分导论》第3章中学到的知识,先写出朴素算法,然后造一些数据,可能就会发现规律。有些时候,问题的答案可能很有特点:对于大多数情况,答案是一样的。据说,在NOIP2013中,有人最后一题不会,愤然打了个随机数,结果得了。

星卯教育-信奥教练tony 6407

SpringBoot中AOP

AOP指的是“面向切面的编程”。 AOP并不是Spring所特有的技术,只是Spring对AOP的支持非常好,在使用Spring框架的情况下,可以更加轻松的实现AOP。 AOP是可以在数据处理流程中统一添加切面,使得各种数据处理流程都可以应用切面中定制的方法。 要使用AOP,首先,需要添加2个新的依赖: <dependency> <groupId>aspe...

李星的博客 300

STM32F103xx / STM32F429VET6最小系统原理图

心血来潮想试一下STM32F4系列和F1系列在编程上有什么差别,手头没有开发板,本着能勤俭节约的原则自己先做一块看看能不能成,看了一下STM32F429VET6的芯片在F429xx中最便宜,对照着数据手册绘制了原理图画了PCB,目前打板中,焊接完如果跑不通回来修改文章。这里我们可以看到,VDD是标准工作电压,VDDA是模拟工作电压,且VDDA必须与VDD等电位,VBAT是备份工作电压,一般接纽扣电池电源,如果存在VREF+引脚,则要求VDDA-VREF+ < 1.2V。截图下来比较糊,不知道为什么。

m0_51294753的博客 1万+

关于Spring中AOP的一些理解

简介:关于AOP的一些笔记。 目录1. AOP简介2.AOP名词解释3.使用AOP3.1 AOP基于xml3.2 AOP基于注解4 AOP通知的执行顺序 1. AOP简介 如果我们想对一个类进行增强,最常见的方式有两种: 继承:通过继承,可以扩展父类的功能,从而得到更强大的类——子类 代理:使用代理,让方法执行前后,再做一些额外的事情,从而获得更强大的类——代理类。 很明显,继承是一种纵向的关...

opt1997的博客 310

VirtualBox安装Win10虚拟机超详细教程(附微软官方镜像下载)

本文提供了一份详细的VirtualBox安装Win10虚拟机教程,涵盖从环境准备、工具下载到系统安装与初始配置的全过程。特别推荐使用微软官方镜像下载,确保系统纯净安全。此外,还分享了性能优化技巧和常见问题解决方案,帮助用户高效搭建稳定的Windows测试环境。

weixin_29243279的博客 920

基于Quartus II软件的FPGA综合实验——多功能数字钟

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言一、设计要求二、设计原理三、设计过程1.数码管扫描模块2.计时模块3.闹钟模块4.闹钟响铃模块5.数码管显示模块6.整点报时功能7.模式选择模块(计时器主控电路)四、实验中遇到的困难及解决方案五、总结 前言 FPGA综合实验——多功能数字钟 基于Quartus II软件 一、设计要求 设计一个能进行时、分、秒计时的十二小时制或二十四小时制的数字钟,并具有定时与闹钟功能,能在设定的时间发出闹铃音,能非常方便地对小时、分钟和秒进.

qq_53022342的博客 2万+

学习AOP时的一个问题

这几天在公司看项目代码,翻到了aop的部分,本着学习的想法看了下使用AspectJ实现对日志的管理。但是在看这段代码的时候有一个问题一直困扰着我,就是代码的执行顺序。 困扰 @Around这个注解的作用之类的就不在这里介绍了,只说其中的一个问题,使用ProceedingJoinPoint类获得切入点之后,用proceed()方法执行被切部分的代码。 问题就在这里,公司的代码中这个Adv

Fake_Armour 389

绕过Google Play:获取Expo Go安卓APK的实用指南

本文为国内安卓开发者提供了绕过Google Play商店获取Expo Go APK的实用指南。针对无法访问Google Play的痛点,详细介绍了通过官方GitHub Releases、可信第三方网站(如APKMirror)及APK下载器等多种安全获取途径,并重点讲解了APK安装、安全验证(核对签名)及常见连接问题的排查方法,帮助开发者顺利开启React Native开发之旅。

weixin_29006701的博客 578

如何判断某个方法的返回值是不是void

在一些动态程序中,可能需要判断方法的返回值类型。下面这个例子演示了如何判断方法返回值是否为void(其实也就是没有返回值)写法有点特殊,void其实是一个结构体。但没有办法直接比较,而要用typeof var method = message.MethodInfo; if (method.ReturnType == typeof(void)) //如果方法

陈希章@中国 2468

OpenClaw进阶实战(二十五):抖音企业号——私信回复与视频评论分析

本文介绍了抖音企业号自动化运营的技术方案,重点解决私信互动效率低和风控严格两大挑战。文章分析了抖音集成的三大技术壁垒(视频复杂性、风控体系、封闭API)并对比了三种技术路径的优缺点。针对不同规模的运营主体,推荐官方API+RPA混合架构或真机RPA+AI辅助的方案。 详细讲解了环境准备步骤,包括抖音Skill安装、Cookie获取和配置文件设置。核心实现部分展示了私信自动回复功能的安全合规实现,包含意图分类、优先级排序、延迟发送等防封禁机制,并提供了完整的Python代码示例。该方案通过模拟人工操作、限制日

PeterPan的博客 159

模型预测控制(MPC)算法介绍

模型预测控制(Model Predictive Control,MPC)是一种先进的控制策略,广泛应用于工业过程控制、机器人控制、电力系统等领域。它基于系统的模型,通过滚动优化来预测系统未来的行为,并据此确定当前的最优控制输入。

AI的内部世界的博客 7175

详解Spring AOP

Aspect Oriented Programming(面向切面编程),OOP是面向对象编程(开发的时候把一个个都抽象成对象来开发),两者的维度不同,处理的事情不同切⾯就是指某⼀类特定问题, 所以AOP也可以理解为⾯向特定⽅法编程。面向切面编程就是针对某一类特定问题统一进行编程比如people类有自己的属性和行为,但是有小一部分人生病要去医院看病,看病这个业务逻辑就不属于哪一个类,因为people泛指所有人,所有人不会都看病。

N_0050的博客 2030

[QMT和ptrade量化交易小白入门]-125、菜场大妈加上四大现金行业指数风控,最大回撤从22%减少了一半

群里面有人建议,在菜场大妈策略的基础上,加入申万的行业指数(银行,钢铁,有色,煤炭)测算其宽度,当这四大行业其中有一个高就会清仓(用来控制回撤)。这背后的逻辑是,在存量资金博弈的市场环境中,资金总量相对固定,当银行、钢铁、有色、煤炭等大市值周期行业因基本面改善(如涨价、政策催化)或避险需求而走强时,会吸引大量资金涌入,导致其他板块(尤其是小市值股票)面临流动性虹吸。经过回测,对比上一个版本发现确实是可以降低一半的回撤,最大回撤从22.3%降到了11.4%,而且有很多时间是空仓等待。

木头大左的博客 241

Spring AOP详细介绍

什么是AOP AOP(Aspect-OrientedProgramming,面向切面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,...

JinXYan的博客 7万+

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Spring AOP 详解

Spring AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架提供的一种编程范式,它允许开发者将横切关注点(如日志、事务管理、权限检查等)与业务逻辑分离,从而提高代码的模块化和可维护性。Spring AOP 基于代理机制实现,它为Spring应用提供了声明式事务管理等功能。

2301_80035594的博客 6824

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Spring AOP

AOP(Aspect-Oriented Programming,面向切面编程):是一种软件开发的编程范式,旨在将横切关注点(cross-cutting concerns)与核心业务逻辑分离,以提高代码的模块化性、可维护性和复用性

2301_76161469的博客 5338

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

【Spring】AOP

AOP(Aspect Oriented Programming) 是一种编程范型,即面向切面编程。什么是面向切面编程?切面就是指某一类特定问题,所以AOP也可以理解为面向特定方法编程。面向编程旨在通过分离横切关注点来提高代码的模块化和可维护性,允许开发者将那些与业务逻辑无关,但又需要在多个地方使用的功能(如日志记录、事务管理、安全性等)从业务逻辑中分离出来。在前面我们的登录校验,用了拦截器,其实也是对AOP思想的一种实现。统一数据返回格式和统一异常处理也是AOP的一种实现。

zhyhgx的博客 1916

【Spring】Spring AOP

SpringAOP 认识和实现原理

bit me的博客 1949

Spring Aop实例

在上篇博文中,我向大家介绍了Aop重要概念和教程,这回给出代码示例。 一、XML方式 1. TestAspect:切面类 package com.spring.aop; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; public class TestAspect { pu

鹏霄万里展雄飞 8万+

Spring 配置AOP Spring注解配置AOP Spring XML 配置AOP Spring Aspect AOP

Spring 配置AOP Spring注解配置AOP Spring XML 配置AOP Spring Aspect AOP

HaHa_Sir的博客 1115
上一篇: Spring/IoC、DI、Bean
下一篇: SpringBoot原理篇-Bean的8种加载方式
南懿烨曦
博客等级 码龄6年 108粉丝 35原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值