2023.12.2 关于 Spring AOP 详解

news2025/1/11 14:04:53

目录

Spring AOP

Spring AOP  常见使用场景

 AOP 组成

切面(类)

切点(方法)

通知

​编辑

前置通知(@Before)

后置通知(@After)

返回通知(@AfterReturning)

异常通知(@AfterThrowing)

环绕通知(@Around)

连接点

Spring AOP 实现  

 切点表达式说明

 Spring AOP 实现原理

织入

动态代理

JDK 动态代理

CGLIB


Spring AOP

  • AOP (Aspect Oriented Programming)译为 面向切面编程
  • AOP 为一种思想,是对某一类事情的集中处理
  • Spring AOP 是一个框架,提供了对 AOP 思想的实现
  • Spring AOP 是 Spring 的三大核心思想之一,另外两个是 IOC(控制反转)和 DI(依赖注入)

实例理解

  • 在我们程序中,经常存在一些系统性的需求
  • 这些需求代码会散落穿插在各个业务逻辑中,非常冗余且不利于维护,具有极高的耦合性
  • AOP 的目的就是将这些非业务代码完全提取出来,与业务代码分离,并寻找节点切入业务代码中

Spring AOP  常见使用场景

  • 统一登录检测机制
  • 统一方法的执行时间统计
  • 统一的返回格式设置
  • 统一异常处理
  • 事务的开始和提交

实例理解

  • 假设我们有一个 Web 应用其中有很多需要用户登录后才能访问的页面
  • 为了避免在每个需要登录的方法中都检查用户是否已经登录
  • 我们便可以使用 Spring AOP 来解决该问题

 AOP 组成

切面(类)

  • 在程序中就是对某一功能进行统一处理的类
  • 这个类包含了很多方法,这些方法就是由 切点 和 通知 组成

切点(方法)

  • 定义一个进行主动拦截的规则
  • 所谓的拦截就是 对用户向服务器发送的请求进行拦截,检测用户的操作是否符合预期,发现问题并统一处理的过程

通知

  • 通知就是 AOP 的具体执行动作
  • 在程序中被拦截后会触发一个具体的动作,即通知中具体实现的业务代码

  • 在 Spring 中可以在方法上使用以下注解,设置方法为通知方法,在满足条件后会通知本方法进行调用

前置通知(@Before)

  • 执行目标方法(实际要执行的方法)之前执行的方法

后置通知(@After)

  • 执行了目标方法之后执行的方法

返回通知(@AfterReturning)

  • 目标方法返回(return)的时候,执行的方法

异常通知(@AfterThrowing)

  • 在执行目标方法抛出异常时,执行的方法
  • 通常结合事务一起使用,如果未抛出异常则提交成功,如果抛出异常则回滚事务

环绕通知(@Around)

  • 在目标方法调用前、后都执行的通知
  • 如果已经有了前置和后置通知,再使用环绕通知,那么周期范围就在前置通知之前,后置通知之后
  • 通常可用于计算目标方法执行的时间


连接点

  • 所有可能触发切点的点就叫做连接点

Spring AOP 实现  

  • 此处我们想实现拦截 UserController 类中的所有方法

添加 Spring Boot AOP 依赖

  • 创建 Spring Boot 项目时,无法选择添加 Spring boot AOP 依赖
  • 所以我们可以选择进入 中央仓库 来选择与当前 Spring Boot 版本相对应的 AOP

<dependency>
    <groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

定义切面(类)

  • 使用 @Aspect 注解修饰该类,告诉 Spring Boot 该类为一个切面类
package com.example.demo.component;

import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect // 切面
@Component // 不能省略
public class UserAspect {
}

定义切点(方法)

  • 定义拦截规则,实现拦截 UserController 类中的所有方法
  • 使用 @Pointcut 修饰一个方法,该方法无需有方法体
  • 方法名就是起到一个标识的作用,标识通知方法具体指的是哪一个切点,因为切点可能有很多个
package com.example.demo.component;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect // 切面
@Component // 不能省略
public class UserAspect {
    
//    切点(配置拦截规则)
    @Pointcut("execution(* com.example.demo.controller.UserController.*(..))")
    public void pointcut() {
    }
}

创建通知

  • 此处我们创建三个通知
  • 前置通知、后置通知、环绕通知
package com.example.demo.component;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Aspect // 切面
@Component // 不能省略
public class UserAspect {

    //    切点(配置拦截规则)
    @Pointcut("execution(* com.example.demo.controller.UserController.*(..))")
    public void pointcut() {
    }

    /*
     * 前置通知
     * */
    @Before("pointcut()")
    public void beforeAdvice() {
        System.out.println("执行了前置方法");
    }

    /*
    * 后置通知
    * */
    @After("pointcut()")
    public void afterAdvice() {
        System.out.println("执行了后置方法");
    }

     /*
    * 环绕通知
    * 此处的 joinPoint 就是连接点,即方法本身
    * */
    @Around("pointcut()")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        Object obj = null;
        System.out.println("进入了环绕通知");
        obj = joinPoint.proceed();
        System.out.println("退出了环绕通知");
//        最后将执行的结果交给框架
        return obj;
    }
}

创建连接点

  • 此处我们对照 切点的拦截规则
  • 创建一个 UserController 类
  • 并在该类中创建两个连接点
  • 当我们在浏览器中访问这两个连接点时,会触发切点的拦截规则,对其进行拦截,然后执行各种通知
package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @RequestMapping("/user/sayhi")
    public String sayHi() {
        System.out.println("执行了 sayHi 方法");
        return "hi spring boot aop";
    }

    @RequestMapping("/user/login")
    public String login() {
        System.out.println("执行了 login 方法");
        return "do user login";
    }
}

执行结果

  • 运行 Spring Boot 项目
  • 此处我们在浏览器中输入对应的 URL 地址,访问 UserController 中的 sayHi 方法


图示理解

 切点表达式说明

  • 该切点表达式属于 AspectJ 的语法
  • execution( <修饰符> <返回类型> <包.类.方法(参数)> <异常> )


实例理解

 Spring AOP 实现原理

  • Spring 的切面是代理类实现的
  • 代理类包裹了 目标对象
  • 即 用户只能先通过代理类,进行校验,如果没有问题才会进一步访问到目标对象

织入

  • 指代理生成的时机
  • 一般情况下,Spring AOP 动态代理的植入时机是程序的运行期

动态代理

  • Spring AOP 是构建在动态代理基础上的,所以 Spring 对 AOP 的支持局限于方法级别的拦截
  • Spring AOP 支持 JDK Proxy 和 CGLIB 方式实现动态代理

JDK 动态代理

  • 基于接口实现
  • 底层通过反射实现
  • 要求代理类一定要实现接口

CGLIB

  • 基于类的子类实现
  • 底层通过字节码增强技术生成子类实现
  • 不能代理被 final 修饰的类,因为其无法生成子类

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

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

相关文章

认识DHT11温湿度传感器并制作温度报警器

Arduino UNO Arduino IDE开发环境 Arduino DHT11温湿度传感器 ​ 一、认识Arduino的DHT11温度湿度传感器 DHT传感器由电容式湿度传感器和热敏电阻两部分组成。除此之外&#xff0c;模块内部还有一些模拟信号到数字信号的转换&#xff0c;将温度湿度以数字信号的方式输…

EPS地形图绘制技巧--快捷键

如何导入外业点数据&#xff1f; &#xff08;1&#xff09;打开EPS软件&#xff0c;新建一个工程。如下&#xff1a; &#xff08;2&#xff09;在【文件】-【输入输出】-【调入坐标文件数据】中&#xff0c;调入测量点数据&#xff0c;如下&#xff1a; &#xff08;3&#…

asp.net_sql2008公司人事管理系统

登录模块 流程图&#xff1a; ◆ 职工输入用户名、密码并选择登录身份&#xff0c;根据选择的身份做不同的操作 ◎ 若选择的是“职工”&#xff0c;系统将查询数据库中的用户表Users的记录&#xff0c;用户名密码核对正确后加载职工主界面&#xff1b; ◎ 若选择的是“管理员…

Find My扩展坞|苹果Find My技术与扩展坞结合,智能防丢,全球定位

扩展坞又称端口复制器&#xff0c;是专为笔记本电脑设计的一种外置设备。通过复制甚至扩展笔记型计算机的端口&#xff0c;可使笔记本电脑与多个配件或外置设备&#xff08;如电源适配器、网线、鼠标、外置键盘、打印机及外置显示器&#xff09;方便的一站式连接。随着全球经济…

Perplexity发布两款LLM模型:pplx-7b-online和pplx-70b-online 可利用实时互联网数据查询

Perplexity AI&#xff0c;一家创新的人工智能初创公司&#xff0c;近日推出了一项能够改变信息检索系统的解决方案。该公司推出了两款新的大语言模型&#xff08;LLMs&#xff09;&#xff0c;分别是pplx-7b-online和pplx-70b-online&#xff0c;标志着首次通过API公开访问在线…

C# OpenVINO 模型信息查看工具

目录 效果 支持模型 项目 代码 下载 C# OpenVINO 模型信息查看工具 效果 支持模型 ONNX format (*.onnx) PDPD (*.pdmodel) TF (*.pb) TFLite (*.tflite) 项目 代码 using Sdcb.OpenVINO; using System; using System.Collections.Generic; using System.Text; using…

docker部署typecho博客

文章目录 1.安装git2.安装compose3.拉取仓库4.创建目录5.配置文件修改6.启动容器7.修改MYSQL数据库8.安装成功9.参考GitHub文档 1.安装git 安装git yum -y install git2.安装compose &#xff08;docker安装参考&#xff1a;docker基本知识&#xff09; 确保已经安装了 Doc…

数组中第k个最大元素(优先队列)

class Solution { public:int findKthLargest(vector<int>& s, int k) {priority_queue<int> pq;for(int i 0; i < s.size(); i){pq.push(s[i]);}for(int i 1; i < k; i){pq.pop();}return pq.top();} }; priority_queue<int> pq为优先队列 s.s…

傅里叶变换及其在机器学习中的应用

​​​​​​​一、介绍 傅立叶变换是一种数学技术&#xff0c;在各个科学和工程领域发挥着关键作用&#xff0c;其应用范围从信号处理到量子力学。近年来&#xff0c;它在机器学习领域发现了新的意义。本文探讨了傅里叶变换的基础知识及其在机器学习应用中日益增长的重要性。 …

万界星空科技注塑mes

塑料制品产业虽然有一定的规模和基础&#xff0c;但存在自主创新能力低、“散小乱”、品牌效应不明显、行业创新能力与庞大的产业不匹配或支撑不足等问题&#xff0c;塑料加工行业还处在质量型产业的初期&#xff0c;抗风险能力低。注塑行业6大痛点&#xff1a; 1.生产效率低 注…

堆排序(C语言)

前言 在上一篇内容&#xff1a;大小堆的实现&#xff08;C语言&#xff09;&#xff0c;我们实现了关于创建大小堆的各函数与实现。但是如果突然要使用一个堆排序但是此时并没有一个现成的堆&#xff0c;这就需要花费时间去新建实现堆的插入删除这些操作从而实现一个堆&#xf…

如何有效进行主数据治理

在企业信息化建设不断推进、逐渐进行数字化转型的今天&#xff0c;几乎所有的企业都卷入到数据及其处理&#xff08;数据收集、存储、检索、传输、分析和表示&#xff09;的浪潮中&#xff0c;数据已成为重要生产要素和无形资产&#xff0c;针对主数据的全生命周期管理迫在眉睫…

老司机带你一课学透,核心分布式事务框架之Alibaba Seata框架经验总结

在现代分布式系统中&#xff0c;保证数据的一致性和可靠性是一项重要的挑战。Alibaba Seata是一款开源的分布式事务解决方案&#xff0c;它提供了强大的支持&#xff0c;帮助开发者处理分布式事务。本文将向您介绍Alibaba Seata框架&#xff0c;并分享一些使用该框架的经验总结…

Java零基础——SpringSecurity篇

1.认证授权的基础概念 1.1 什么是认证&#xff08;登录&#xff09; 进入移动互联网时代&#xff0c;大家每天都在刷手机&#xff0c;常用的软件有微信、支付宝、头条等&#xff0c;下边拿微信来举例子说明认证相关的基本概念&#xff0c;在初次使用微信前需要注册成为微信用户…

31名!美创科技再次入选《中国网络安全企业100强》

12月1日&#xff0c;安全牛联合中国计算机学会抗恶劣环境计算机专业委员会、信息产业信息安全测评中心正式发布第十一版《中国网络安全企业100强》&#xff08;以下简称“100强”&#xff09;。 美创科技再次入选“中国网络安全企业100强”&#xff0c;位列31名&#xff08;数据…

07、基于LunarLander登陆器的强化学习案例(含PYTHON工程)

07、基于LunarLander登陆器的强化学习&#xff08;含PYTHON工程&#xff09; 开始学习机器学习啦&#xff0c;已经把吴恩达的课全部刷完了&#xff0c;现在开始熟悉一下复现代码。全部工程可从最上方链接下载。 基于TENSORFLOW2.10 0、实践背景 gym的LunarLander是一个用于…

无需服务器,无需魔法,拥有一个微信机器人就是这么简单

前情提要 还没看过的朋友可以看一下上一篇文章《拥有一个微信机器人总共需要几步&#xff1f;》在这篇文章里&#xff0c;我们提到&#xff0c;创建微信机器人需要一个大前提--你得有一台服务器。现在&#xff0c;不再需要了&#xff01;没错&#xff0c;上一篇提到的Serverles…

Python爬虫:使用Scrapy框架进行高效爬取

Python爬虫可使用的架构有很多&#xff0c;对于我而言&#xff0c;经常使用Scrapy异步处理框架Twisted&#xff0c;其实意思很明确&#xff0c;Scrapy可以实现多并发处理任务&#xff0c;同一时间将可以处理多个请求并且大大提高工作效率。 Scrapy是一个强大且高效的Python爬虫…

文章阅读——Scaffolding protein functional sites using deep learning

1.最终幻想: 无中生有的蛋白质从头设计 零.导读 近几年&#xff0c;蛋白质结构预测领域连续取得重大突破。首先是【AlphaFold】&#xff0c;在可以充分利用共进化信息结合深度神经网络生成空间约束条件并降低相空间的搜索&#xff0c;极大地帮助了蛋白质的结构建模&#xff0…

扁平按钮样式

上图 代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>扁平按钮</title><style>body {margin: 0;padding: 0;height: 100vh;display: flex;justify-content: center;ali…