Spring AOP知识点详解

news2024/11/15 10:57:04

Spring AOP是 Spring最核心的能力,那到底什么是AOP呢,今天了不起带大家了解一下。

AOP是什么

AOP(Aspect Oriented Programming):面向切面编程,是OOP(面向对象编程)的一个延续,其和OOP一样,也是一种编程思想,不过AOP是一种横向开发模式。

OOP,面向对象,允许开发者定义纵向的关系,但并适用于定义横向的关系,导致了大量代码的重复,而不利于各个模块的重用。
AOP,一般称为面向切面,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证.日志.事务处理。
AOP实现的关键在于代理模式,AOP代理主要分为静态代理动态代理。静态代理的代表为AspectJ动态代理则以Spring AOP为代表。

  1. AspectJ是静态代理的增强,所谓静态代理,就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强,他会在编译阶段将AspectJ(切面)织入到Java字节码中,运行的时候就是增强之后的AOP对象。
  2. Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。

Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理:

  1. JDK动态代理只提供接口代理,不支持类代理,核心InvocationHandler接口和Proxy类,InvocationHandler 通过invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起,Proxy利用 InvocationHandler动态创建一个符合某一接口的的实例, 生成目标类的代理对象。
  2. 如果代理类没有实现 InvocationHandler 接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
  3. 静态代理与动态代理区别在于生成AOP代理对象的时机不同,相对来说AspectJ的静态代理方式具有更好的性能,但是AspectJ需要特定的编译器进行处理,而Spring AOP则无需特定的编译器处理。
    InvocationHandler invoke(Object proxy,Method method,Object[] args)proxy是最终生成的代理实例; method 是被代理目标实例的某个具体方法;args 是被代理目标实例某个方法的具体入参, 在方法反射调用时使用。

AOP使用场景

AOP的主要作用就是减少代码量,提高代码的可重用性,有利于未来的可操作性与可维护性。
主要操作就是将所有模块中共同拥有的代码,单独抽取出来,放在一块地方,在主代码运行之前或之后,或主程序运行的其他时间点执行这块代码。也可以理解成把这些单独抽出来的代码封装成一个个单独的方法,但是这些方法的执行不需要我们在程序中进行显示地调用,而是通过动态代理的方式来帮助我们执行这些方法。AOP的主要应用场景是一些相似性代码比较高的场景,比如:权限认证,日志,事务等。

AOP术语

  1. 连接点(Joinepoint):是程序执行的某个特定位置,如类开始初始化前、类初始化后、类的某个方法调用前/后、方法抛出异常后。一个类或者一段程序代码拥有一些具有边界性质的特定点,这些特定点就称为 “连接点” 。这边有个注意的点就是spring的链接点只支持方法,也就是只能是方法在调用前,调用后,抛出异常后。
  2. 切点(Pointcut): 切点就是能够定位到特定连接点的点。也就是能够通过切点知道程序在哪个连接点之前或之后执行。
  3. 增强(Advice): 增强说白了就是你想要在切点上执行的代码逻辑,也就是在连接点之前或之后执行的那段代码。
  4. 目标对象(Target): 就是你要插入代码的类,也就是连接点所在的类。
  5. 引介(Introduction): 是一种特殊的增强,为类添加一些属性和方法。
  6. 织入(Weaving):是一个过程,就是将增强添加到目标类具体连接点上的过程。
  7. 代理(Proxy): 就是融合了目标类和增强逻辑后生成的那个对象
  8. 切面(Aspect): 由切点和增强组成,包含了切点的定义与增强的代码逻辑的定义

AOP使用入门样例

  1. 引入依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
  1. 定义一个Controller作为测试
public class AopController {

    @RequestMapping("/hello")
    public String sayHello(){
        System.out.println("hello");
        return "hello";
    }
}
  1. 定义切面类

Spring采用@AspectJ注解对POJO进行标注,该注解表明该类不仅仅是一个POJO,还是一个切面。切面是切点和通知的结合,那么定义一个切面就需要编写切点和通知。

@Pointcut注解可以在一个切面内定义可重用的切点。

Spring切面粒度最小是达到方法级别,execution表达式可以用于明确指定方法返回类型,类名,方法名和参数名等与方法相关的部件,并且实际开发中,大部分需要使用AOP的业务场景也只需要达到方法级别即可,因而execution表达式的使用是最为广泛的。

@Aspect
@Component
public class AopAdvice {

    @Pointcut("execution (* com.xxx.aop.controller.*.*(..))")
    public void test() {

    }
}

切点通过@Pointcut注解已经定义好,那接下来就需要定义通知。
AOP通知有五种类型,分别是

前置通知(@Before):在目标方法调用之前调用通知

后置通知(@After):在目标方法完成之后调用通知

环绕通知(@Around):在被通知的方法调用之前和调用之后执行自定义的方法

返回通知(@AfterReturning):在目标方法成功执行之后调用通知

异常通知(@AfterThrowing):在目标方法抛出异常之后调用通知

代码中定义了三种类型的通知,使用@Before注解标识前置通知,打印“beforeAdvice…”,使用@After注解标识后置通知,打印“AfterAdvice…”,使用@Around注解标识环绕通知,在方法执行前和执行之后分别打印“before”和“after”。

@Before("test()")
public void beforeAdvice() {
    System.out.println("beforeAdvice...");
}

@After("test()")
public void afterAdvice() {
    System.out.println("afterAdvice...");
}

@Around("test()")
public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) {
    System.out.println("before");
    try {
        proceedingJoinPoint.proceed();
    } catch (Throwable t) {
        t.printStackTrace();
    }
    System.out.println("after");
}
  1. 结果

运行AopApplication,在浏览器访问http://localhost:8080/hello,不出意外,控制台输出如图所示:

图片

AOP总结

纸上得来终觉浅,绝知此事要躬行,大家实践一下,也就知道具体的AOP是什么了,只要实践后,一切都变容易了。

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

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

相关文章

在Linux下做性能分析3:perf

介绍 ftrace的跟踪方法是一种总体跟踪法&#xff0c;换句话说&#xff0c;你统计了一个事件到下一个事件所有的时间长度&#xff0c;然后把它们放到时间轴上&#xff0c;你可以知道整个系统运行在时间轴上的分布。 这种方法很准确&#xff0c;但跟踪成本很高。所以&#xff0…

有道云笔记迁移到自建服务器Joplin

当前有道云笔记各项业务开始逐渐向会员靠拢&#xff0c;如一开始不受限的多端同步现在非会员限制成了两个终端&#xff0c;估计以后会有越来越多的免费内容会逐渐的向会员转移&#xff0c;因此博主开始考虑自建服务器来搞一个云笔记服务端。 因博主已有黑群晖&#xff0c;并且有…

OK3588运行python程序对摄像头数据进行图像处理

OK3588运行python程序读取usb摄像头 硬件连接用工具测试验证摄像头工作正常python 读取usb摄像头并进行图像处理 硬件连接 把usb摄像头插入HOST的usb接口。 在串口终端运行 sudo v4l2-ctl --list-devices 如下图 当前的usb设备是 /dev/video74 用工具测试验证摄像头工作正常…

基于深度学习的高精度80类动物目标检测系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于深度学习的高精度80类动物目标检测识别系统可用于日常生活中或野外来检测与定位80类动物目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的80类动物目标检测识别&#xff0c;另外支持结果可视化与图片或视频检测结果的导出。本系统采用YO…

#4. 背包

4030: 背包 题目内容 有 n n n 个物品&#xff0c;每个物品有大小 w i w_i wi​ 和价值 v i v_i vi​&#xff0c;再给定一个整数 k k k 和背包大小 m m m&#xff0c;对每个 1 ≤ i ≤ n − k 1 1 \le i \le n - k 1 1≤i≤n−k1&#xff0c;求出如果只能选择 i i …

Linux中makefile

第一个版本的makefile Makefile的依赖是从上至下的&#xff0c;换句话说就是目标文件是第一句里的目标&#xff0c;如果不满足执行依赖&#xff0c;就会继续向下执行。如果满足了生成目标的依赖&#xff0c;就不会再继续向下执行了。 Make会自动寻找依赖条件所用到的文件&…

uni-app的H5版本下载跨域问题

前端能正常访问图片&#xff0c;但无法下载 因为路径不经过业务代码&#xff0c;所以需要在nginx配置跨域 代码&#xff1a; add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods GET, POST, OPTIONS; add_header Access-Control-Allow-H…

【黑客】网络安全靠自学?你不要命了!

1️⃣网安现状 ❗本文面向所有 想要涉足网安领域 或 已经涉足但仍处在迷茫期 的伙伴&#xff0c;如果你月薪达到了3w&#xff0c;那么请你离开。 如果没有&#xff0c;希望你继续看下去&#xff0c;因为你人生的转折点将从这篇文章开始。 ✈️网络安全&#xff0c;一个近几年大…

路径规划算法:基于斑马优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于斑马优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于斑马优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化算法斑马…

Keil5新建51单片机demo工程模板

51单片机新建工程使用到的软件有keil5&#xff0c;首先安装好keil5软件&#xff0c;安装教程在:【Keil&#xff08;C51&#xff09;介绍、下载、安装、注册与2个补丁】Keil&#xff08;C51&#xff09;介绍、下载、安装与2个补丁_西晋的no1的博客-CSDN博客 一、新建一个空工程 …

【QT】——基础窗口类QMainWindow

目录 1.概念 2.菜单栏——QMenuBar 3.工具栏 添加QAction 工具栏属性设置 5.状态栏——QStatusBar 6 停靠窗口 属性设置 1.概念 QMainWindow 是标准基础窗口中结构最复杂的窗口&#xff0c;QMainWindow继承QWidget&#xff0c;他在QWidget的基础上提供了菜单栏&#…

网络编程 socket

目录 网络编程 套接字&#xff08;socket&#xff09;1. 认识端口号2. TCP协议3. UDP协议4. 网络字节序列5. 常见的套接字6. socket编程接口6.1 socket常见APIsocket函数recvfrom函数sendto函数read函数 从tcp socket中读取接收数据 6.2 sockaddr结构6.3 地址转换函数6.4 udp s…

input输入日期时间,自动格式化组件/工具

input输入日期时间&#xff0c;自动格式化组件/工具 组件/工具使用说明 只能输入日期时间&#xff0c;不能选择日期时间格式 yyyy-MM-dd HH:mm:ss基于VUE框架输入效果见下图 组件/工具解决的痛点 组件库日期时间组件&#xff0c;选日期时间很花时间 例如想快速得到 2021-1…

OJ练习第137题——有序链表转换二叉搜索树

有序链表转换二叉搜索树 力扣链接&#xff1a;109. 有序链表转换二叉搜索树 题目描述 给定一个单链表的头节点 head &#xff0c;其中的元素 按升序排序 &#xff0c;将其转换为高度平衡的二叉搜索树。 本题中&#xff0c;一个高度平衡二叉树是指一个二叉树每个节点 的左右…

[golang gin框架] 40.Gin商城项目-微服务实战之Captcha验证码微服务

本次内容需要 gin框架基础知识, golang微服务基础知识才能更好理解 一.Captcha验证码功能引入 在前面,讲解了微服务的架构等,这里,来讲解前面商城项目的 Captcha验证码 微服务 ,captcha验证码功能在前台,后端 都要用到 ,可以把它 抽离出来 ,做成微服务功能 编辑 编辑 这个验证码…

MySQL 第七天作业 nosql作业

作业一&#xff1a;string list hash结构中&#xff0c;每个至少完成5个命令&#xff0c;包含插入 修改 删除 查询&#xff0c;list 和hash还需要增加遍历的操作命令 1、 string类型数据的命令操作&#xff1a; &#xff08;1&#xff09; 设置键值&#xff1a; set key1 re…

C++基础与深度解析01——函数基本组成+函数传参的三种方法

0.前期准备 请安装Visual Studio 并学习基本的新建项目、新建CPP文件以及运行代码。 1.从Hello World 开始 1.1代码内容 函数功能&#xff1a;打印“Hello World” #include<iostream> int main() { std::cout << "Hello World" << std::endl…

学习babylon.js --- [1] 初次体验和安装

babylon.js是微软推出的Web3D库&#xff0c;本文写作时版本是6.x&#xff0c;官方介绍如下&#xff0c; 看这意思是6.x系列的版本大大提高了性能&#xff0c;并提供了很多新特性。其Github地址是https://github.com/BabylonJS/Babylon.js 本篇文章讲述使用babylon.js的初次体…

申请阿里云服务器并搭建公网可支持数据上传的HTTP服务器

1. 前言 拥有一台自己的云服务器可以做很多事情。阿里云服务器毫无疑问是国内最好的。 阿里云服务器可以用于各种互联网应用的搭建和运行&#xff0c;提供稳定、高性能的服务。 阿里云服务器的用途&#xff0c;包括但不限于以下几个方面&#xff1a; 网站托管&#xff1a;可以将…