SpringAOP详解

news2025/1/31 11:31:10

目录

前言:

相关概念

切点表达式规则

代码演示

SpringAOP实现原理

织入(代理的生成时机)

JDK和CGLIB区别

小结:


前言:

    AOP(Aspect Oriented Programming)是思想(面向切面编程),对某一类事情的统一处理。Spring AOP是思想的具体实现框架。

相关概念

1)切面(类)
    某一方面的具体内容处理就是一个切面。比如用户登录判断就是一个切面(接口对于登录权限的校验)。
2)切点(方法)
    定义拦截规则。比如切面对于哪些接口都需要进行判断。
3)通知(方法的具体实现)
    执行AOP业务(具体需要执行的拦截方法)

  • 前置通知:在目标方法(实际要执行的方法)调用之前执行的通知。
  • 后置通知:在目标方法执行之后的通知。
  • 环绕通知:在目标方法执行前,后都执行的通知。
  • 异常通知:在目标方法抛异常执行的通知。
  • 返回通知:在目标方法返回执行的通知。

4)连接点
    所有可能触发切点的点就是连接点(被这个切面所处理的点)。

切点表达式规则

    切点表达式由切点函数组成,其中execution()是最常用的切点函数,用来匹配方法。

语法:

    execution(<修饰符><返回类型><包.类.方法(参数)><异常>)

    修饰符和异常可以省略(一般异常都是省略)

示例:

    execution(* com.example.demo.controller.UserController.*(..))

    匹配UserController类下的任意方法,参数任意。返回值任意。

注意:

    这种表达式的书写是非常繁琐的,目前有更好的AOP实现,可以更加灵活的配置。

代码演示

设置切面

package com.example.demo.common;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;

@Aspect // 切面
@Component // 添加到框架中
public class UserAOP {

    // 切点(配置拦截规则)
    // 返回值(任意)  具体类(UserController)  方法名(任意)  参数(任意)
    @Pointcut("execution(* com.example.demo.controller.UserController.*(..))")
    public void pointcut(){

    }

    // 前置通知
    @Before("pointcut()")
    public void doBefore() {
        System.out.println("执行了前置通知:" + LocalDateTime.now());

    }

    // 后置通知
    @After("pointcut()")
    public void doAfter() {
        System.out.println("执行了后置通知:" + LocalDateTime.now());
    }

    // 环绕通知
    @Around("pointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("开始执行环绕通知");
        // 执行连接点中的方法(基点)
        Object obj = joinPoint.proceed();
        System.out.println("结束执行环绕通知");
        return obj;

    }
}

定义连接点

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/hello")
    public String hello() {
        System.out.println("执行了hello方法");
        return "hello";
    }

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

    当访问/user/hello这个接口,控制台的打印。

注意:

    可以清楚的看到执行目标方法时,前置通知、后置通知和环绕通知的执行时机。

SpringAOP实现原理

    Spring AOP 是构建在动态代理基础上,因此 Spring 对 AOP 的支持局限于方法级别的拦截(使用动态代理技术实现方法的调用)。

    Spring AOP 支持 JDK Proxy CGLIB 方式实现动态代理。默认情况下,实现了接口的类,使用 SpringAOP 会基于 JDK 生成代理类,没有实现接口的类,会基于 CGLIB 生成代理类。

织入(代理的生成时机)

    织入是把切面应用到目标对象并创建新的代理对象的过程,切面在指定的连接点被织入到目标对
象中。
在目标对象的生命周期里有多个点可以进行织入:

1)编译期

    切面在目标类编译时被织入。这种方式需要特殊的编译器。AspectJ的织入编译器就
是以这种方式织入切面的。

2)类加载期

    切面在目标类加载到JVM时被织入。这种方式需要特殊的类加载器(ClassLoader),它可以在目标类被引入应用之前增强该目标类的字节码。AspectJ5的加载时织入(load-time weaving. LTW)就支持以这种方式织入切面。

3)运行期

    切面在应用运行的某⼀时刻被织入。⼀般情况下,在织入切面时,AOP容器会为目标对象动态创建⼀个代理对象。SpringAOP就是以这种方式织入切面的。

JDK和CGLIB区别

    1)JDK 实现(反射方式),要求被代理类必须实现接口,之后是通过 InvocationHandler 及 Proxy,在运行时动态的在内存中生成了代理类对象,该代理对象是通过实现同样的接口实现(类似静态代理接口实现的方式),只是该代理类是在运行期时,动态的织入统一的业务逻辑字节码来完成。可以代理任意类。性能相对较高,生成代理对象速度较快。

    2)CGLIB 实现(字节码加强技术),被代理类可以不实现接口,是通过继承被代理类(生成目标对象的子类),在运行时动态的生成代理类对象(字节码加强技术)。无法代理 final 类和 final 方法。性能相对较低,生成代理对象速度较慢。

注意:

    在 Spring 框架中,即使用了 JDK 动态代理又使用 CGLIB,默认情况下使用的是 JDK 动态代理,但是如果目标对象没有实现接口,则会使用 CGLIB 动态代理。

小结:

    面向切面编程就是统一功能的处理,SpringAOP实现了这种技术。通过动态代理的方式:JDK动态代理通过反射的方式实现,速度快,要求被代理类必须实现接⼝。CGLIB通过实现代理类的子类实现动态代理(字节码加强技术),代理类不能是final修饰。

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

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

相关文章

文心一言 VS 讯飞星火 VS chatgpt (37)-- 算法导论5.4 1题

一、一个屋子里必须要有多少人&#xff0c;才能让某人和你生日相同的概率至少为1/2? 必须要有多少人&#xff0c;才能让至少两个人生日为 7月 4 日的概率大于 1/2? 文心一言&#xff1a; 一个屋子里必须要有多少人&#xff0c;才能让某人和你生日相同的概率至少为1/2&#…

Linux下ElasticSearch7.9.2安装配置(包含服务器配置、启动停止脚本、开放端口和elasticsearch-head插件的使用)

Linux下ElasticSearch7.9.2安装配置 前言1.下载安装1.1 使用wget的方式下载1.2 官网下载 2.上传到服务器并解压3.修改es配置文件3.1 es目录简介3.2 修改配置文件 4. 创建用户并赋权5. 服务器修改配置5.1 修改文件句柄数和线程数5.2 关闭swapping5.3 修改虚拟内存 6. 启动es6.1 …

“配置DHCP Snooping实验:保护网络中的DHCP服务和防止欺骗攻击“

"配置DHCP Snooping实验&#xff1a;保护网络中的DHCP服务和防止欺骗攻击" 【实验目的】 部署DHCP服务器。熟悉DHCP Snooping的配置方法。验证拓扑。 【实验拓扑】 实验拓扑如图所示。 设备参数如下表所示。 设备 接口 IP地址 子网掩码 默认网关 R1 F0/0 …

腾讯云轻量应用服务器和云服务器区别详细说明

腾讯云轻量应用服务器是什么&#xff1f;腾讯云轻量服务器和云服务器有什么区别&#xff1f;为什么轻量应用服务器费用更低&#xff1f;是因为轻量服务器CPU内存性能比云服务器CVM性能差吗&#xff1f;轻量应用服务器适合中小企业或个人开发者搭建企业官网、博客论坛、微信小程…

基于SPAD / SiPM技术的激光雷达方案

激光雷达(LiDAR)是一种测距技术&#xff0c;近年来越来越多地用于汽车先进驾驶辅助系统(ADAS)、手势识别和3D映射等应用。尤其在汽车领域&#xff0c;随着传感器融合的趋势&#xff0c;LiDAR结合成像、超声波、毫米波雷达&#xff0c;互为补足&#xff0c;为汽车提供全方位感知…

物联网Lora模块从入门到精通(五)光照与温湿度传感器

一、前言 在程序开发中&#xff0c;光照与温湿度的获取是十分常见与重要的&#xff0c;本文我们主要是使用M21温湿度光照三合一传感器&#xff0c;其中温湿度数据通过协议获取&#xff0c;而光照通过ADC获取。 二、代码实现 本文内容较为简单&#xff0c;且后续文章将在本文基…

网络编程Demo:Java的阻塞与非阻塞模式以及Netty

前言 IO既神秘&#xff0c;双简单 IO是什么 从表面理解&#xff0c;IO是输入&#xff08;input&#xff09;、输出(output)的英文首字母的缩写形式&#xff0c;可以简单理解为计算机的输入与输出&#xff0c;描述计算机的数据流动&#xff0c;如使用键盘输入了一个“hello w…

GreenPlum版本升级

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

C语言期末课程设计—【通讯录管理系统】让课程设计不再是痛苦

目录 摘要 第一章 绪论 1.1项目意义 1.2通讯录功能 第二章 详细设计与实现 2.1 Contact程序运行流程图 2.2 AddContact&#xff08;增加&#xff09;函数流程图 2.3 DelContact&#xff08;删除&#xff09;函数流程图 2.4 SearchConact&#xff08;查找&#xff09;…

碳排放预测模型 | Python实现基于机器回归分析的碳排放预测模型——数据清理和准备

文章目录 效果一览文章概述研究内容源码设计参考资料效果一览 文章概述 碳排放预测模型 | Python实现基于机器回归分析的碳排放预测模型——数据清理和准备 研究内容 分析国家在设计用于预测和预测二氧化碳排放的机器学习模型方面的特定记录,利用来自全球绝大多数国家的记录。…

Spring Cloud - 带你认识微服务,简单demo实现服务拆分及远程调用

目录 一、微服务 1.1、简介 1.2、架构工作原理 1.3、架构特点 1.4、简单了解 SpringCloud 二、服务拆分和远程调用 2.1、服务拆分 2.2、微服务远程调用 2.2.1、远程调用分析 2.2.2、具体调用步骤 三、小结 一、微服务 1.1、简介 微服务是一种架构风格&#xff0c;…

React学习之路-准备工作

一、3W React是什么&#xff1f; React 起源于 Facebook 的内部项目&#xff0c;因为该 公司对市场上所有 JavaScript MVC 框架&#xff0c;都不满意&#xff0c;就决定自己写一套&#xff0c;用来架设 Instagram 的网站。做出来以后&#xff0c;发现这套东西很好用&#xf…

linux 环境执行npm没有反应 (省流:卸载重装)

今天早上在执行工程 npm run dev 时&#xff0c;发现没有反应&#xff0c;也没有提示任何错误&#xff0c;就直接跳过了。 接着我又试了试其他命令 npm -v / npm init / npm … 都无效。 windows 下的解决方案 于是我上网查询了一番&#xff0c;发现的确也有其他人遇到这种…

虚函数表不一定总是在对象的起始位置

在我之前的一篇文章 “COM 对象的内存布局”中&#xff0c;作为举例&#xff0c;我将对象的虚函数表指针放置在了底层 C 对象的起始位置&#xff0c;但是值得注意的是&#xff0c;虚函数表指针指向的位置并没有一个实际的标准。即使将虚函数表放置在对象中间&#xff0c;甚至是…

计算机网络编程 | 并发服务器代码实现(多进程/多线程)

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…

基于 Quivr 搭建个人知识库

目录 Quivr介绍 Quivr特性 Quivr演示 Demo with GPT3.5: Demo of the new version&#xff1a; Quivr实战 Quiv 使用的主要技术 Quiv 实践依赖 创建Supabase项目 部署Quiv项目 第一步&#xff1a;现在源码 第二步&#xff1a;设置环境变量 第三步&#xff1a;执行sql 第…

http1.0,http1.1,http2.0,http3.0 区别有哪些

20 世纪 60 年代&#xff0c;美国国防部高等研究计划署&#xff08;ARPA&#xff09;建立了 ARPA 网&#xff0c;这被认为是互联网的起源。70 年代&#xff0c;研究人员基于对 ARPA 网的实践和思考&#xff0c;发明出了著名的 TCP/IP 协议。该协议具有良好的分层结构和稳定的性…

Docker部署开源项目Django-CMS企业内容管理系统

Docker部署开源项目Django-CMS企业内容管理系统 一、Django-CMS介绍1.1 Django-CMS简介1.2 Django-CMS特点 二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本 四、下载django-cms-quic…

JS 之 事件Event对象详解(属性、方法、自定义事件)

一、Event对象 1、简介 ​ 事件event对象是指在浏览器中触发事件时&#xff0c;浏览器会自动创建一个event对象&#xff0c;其中存储了本次事件相关的信息&#xff0c;包括事件类型、事件目标、触发元素等等。浏览器创建完event对象之后&#xff0c;会自动将该对象作为参数传…

NLP——WordNet;Word Similarity; Word Sense Disambiguition

WordNet WordNet是一个广泛使用的英语词汇数据库和语义网络。它由普林斯顿大学认知科学实验室开发&#xff0c;旨在帮助人们理解单词之间的关系和意义。WordNet的主要目标是将英语词汇组织成一种层次结构&#xff0c;其中每个词都与其他相关词联系起来。WordNet中的单词按照它们…