[详解]Spring AOP

 

  • 🎥 个人主页:Dikz12
  • 🔥个人专栏:Spring学习之路
  • 📕格言:吾愚多不敏,而愿加学
  • 欢迎大家👍点赞✍评论⭐收藏

目录

什么是AOP? 

Spring AOP 快速入门

Spring AOP核心概念

切点(Pointcut)

连接点(Join Point) 

通知(Advice)

切⾯(Aspect)  

 通知类型

切点表达式

 execution表达式

@annotation  

Spring AOP 的实现方式

Spring AOP 原理 

代理模式 

动态代理 

CGLIB动态代理实现

 总结


什么是AOP? 

Aspect Oriented Programming(⾯向切⾯编程)

什么是⾯向切⾯编程呢?
切⾯就是指某⼀类特定问题, 所以AOP也可以理解为⾯向特定⽅法编程.
什么是⾯向特定⽅法编程呢?
就是⼀类特定问题. 登录校验拦截器, 就 是对"登录校验"这类问题的统⼀处理. 所以, 拦截器也是AOP的⼀种应⽤.
简单来说: AOP是⼀种思想, 是对某⼀类事情的集中处理.Spring对AOP进行了实现,并提供了一些API,就是Spring AOP.  比如:统一数据格式 和 统一异常处理,也是AOP的一种实现.

Spring AOP 快速入门

实现记录Controller方法每个方法执行花费的时间.

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;@Slf4j
@Aspect
@Component
public class TimeAspect {/*** 查看每个接口所需的时间*/@Around("execution(* com.example.demo.controller.*.*(..))")public Object recordTime(ProceedingJoinPoint joinPoint) throws Throwable {log.info("方法执行前");long start = System.currentTimeMillis();Object result = joinPoint.proceed();long end = System.currentTimeMillis();log.info("方法执行后");log.info(joinPoint+ "消耗时间" +(end-start)+ "ms");return result;}
}

运行效果: 

对程序代码进⾏简单的讲解:
  1.  @Aspect: 标识这是⼀个切⾯类
  2.  @Around: 环绕通知, 在⽬标⽅法的前后都会被执⾏. 后⾯的表达式表⽰对哪些⽅法进⾏增强.
  3. ProceedingJoinPoint.proceed() 让原始⽅法执⾏

 整个代码划分为三部分:

通过上⾯的程序, 我们也可以感受到AOP⾯向切⾯编程的⼀些 优势
  • 代码⽆侵⼊: 不修改原始的业务⽅法, 就可以对原始的业务⽅法进⾏了功能的增强或者是功能的改变
  • 减少了重复代码
  • 提⾼开发效率
  • 维护⽅便

Spring AOP核心概念

切点(Pointcut)

切点(Pointcut), 也称之为"切⼊点"
Pointcut 的作⽤就是提供⼀组规则 (使⽤ AspectJ pointcut expression language 来描述), 告诉程序对 哪些⽅法来进⾏功能增强.

连接点(Join Point) 

满⾜切点表达式规则的⽅法 , 就是连接点. 也就是可以被AOP控制的⽅法
以⼊⻔程序举例, 所有 com.example.demo.controller 路径下的⽅法, 都是连接点。
package com.example.demo.controller;
@RequestMapping("/book")
@RestController
public class BookController {@RequestMapping("/addBook")public Result addBook(BookInfo bookInfo) {//...代码省略}@RequestMapping("/queryBookById")public BookInfo queryBookById(Integer bookId){//...代码省略}
}
上述BookController 中的⽅法都是连接点。(也就是目标方法)
连接点是满⾜切点表达式的元素. 切点可以看做是保存了众多连接点的⼀个集合.
⽐如:
切点表达式: 学校全体教师
连接点就是: 张三,李四等各个⽼师

通知(Advice)

通知就是具体要做的⼯作, 指哪些重复的逻辑,也就是共性功能(最终体现为⼀个⽅法)
⽐如上述程序中记录业务⽅法的耗时时间, 就是通知。

切⾯(Aspect)  

切⾯(Aspect) = 切点(Pointcut) + 通知(Advice)
通过切⾯就能够描述当前AOP程序需要针对于哪些⽅法, 在什么时候执⾏什么样的操作.
切⾯既包含了通知逻辑的定义, 也包括了连接点的定义。
切⾯所在的类, 我们⼀般称为切⾯类(被@Aspect注解标识的类)

 通知类型

Spring中AOP的通知类型有以下⼏种: 

  •  @Around:环绕通知,此注解标注的通知⽅法在⽬标⽅法前,后都被执⾏.
  •  @Before:前置通知,此注解标注的通知⽅法在⽬标⽅法前被执⾏.
  • @After:后置通知,此注解标注的通知⽅法在⽬标⽅法后被执⾏,⽆论是否有异常都会执⾏.
  • @AfterReturning:返回后通知,此注解标注的通知⽅法在⽬标⽅法后被执⾏,有异常不会执⾏.
  • @AfterThrowing:异常后通知,此注解标注的通知⽅法发⽣异常后执⾏.

执行顺序: 

程序发⽣异常的情况下: 

切点表达式

上⾯的代码中, 我们⼀直在使⽤切点表达式来描述切点. 下⾯我们来介绍⼀下切点表达式的语法.
切点表达式常⻅有两种表达⽅式
  1. execution(RR):根据⽅法的签名来匹配
  2. @annotation(RR) :根据注解匹配

 execution表达式

execution(<访问修饰符> <返回类型> <包名.类名.⽅法(⽅法参数)> <异常>)

切点表达式⽀持通配符表达:
1. * :匹配任意字符,只匹配⼀个元素(返回类型, 包, 类名, ⽅法或者⽅法参数)
     a. 包名使⽤ * 表⽰任意包(⼀层包使⽤⼀个*)
     b. 类名使⽤ * 表⽰任意类
     c. 返回值使⽤ * 表⽰任意返回值类型
     d. ⽅法名使⽤ * 表⽰任意⽅法
     e. 参数使⽤ * 表⽰⼀个任意类型的参数
2. .. :匹配多个连续的任意符号, 可以通配任意层级的包, 或任意类型, 任意个数的参数
     a. 使⽤ .. 配置包名,标识此包以及此包下的所有⼦包
     b. 可以使⽤ .. 配置参数,任意个任意类型的参数

@annotation  

实现步骤:
  1. 编写⾃定义注解
  2. 使⽤ @annotation 表达式来描述切点
  3. 在连接点的⽅法上添加⾃定义注解

1.⾃定义注解 @MyAspect 

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAspect {}

 2.使⽤ @annotation 切点表达式定义切点

@RestController
@Slf4j
@Aspect
public class MyAspectDemo {@Before("@annotation(com.example.demo.aspect.MyAspect)")public void doBefore() {log.info("MyAspect -> Before ...");}@After("@annotation(com.example.demo.aspect.MyAspect)")public void doAfter() {log.info("MyAspect -> After ...");}
}

3.添加⾃定义注解  

public class TestController {@MyAspect@RequestMapping("/t2")public String t2(){return "t2";}}

Spring AOP 的实现方式

  1. 基于注解 @Aspect (最常用)
  2.  基于⾃定义注解 (参考⾃定义注解 @annotation 部分的内容)
  3.  基于Spring API (通过xml配置的⽅式, ⾃从SpringBoot ⼴泛使⽤之后, 这种⽅法⼏乎看不到了, 课 下⾃⼰了解下即可)
  4. 基于代理来实现(更加久远的⼀种实现⽅式, 写法笨重, 不建议使⽤

Spring AOP 原理 

Spring AOP的原理, 也就是Spring 是如何实 现AOP的.
Spring AOP 是基于动态代理实现的.(也就是代理模式中的动态代理)

代理模式 

在某些情况下, ⼀个对象不适合或者不能直接引⽤另⼀个对象, ⽽代理对象可以在客⼾端和⽬标对象之 间起到中介的作⽤.
使⽤代理前:

使用代理后: 

 

 生活中的代理:

  • 艺⼈经纪⼈: ⼴告商找艺⼈拍⼴告, 需要经过经纪⼈,由经纪⼈来和艺⼈进⾏沟通.
  • 房屋中介: 房屋进⾏租赁时, 卖⽅会把房屋授权给中介, 由中介来代理看房, 房屋咨询等服务.
  • 经销商: ⼚商不直接对外销售产品, 由经销商负责代理销售.
静态代理: 由程序员创建代理类或特定⼯具⾃动⽣成源代码再对其编译, 在程序运⾏前代理类的
.class ⽂件就已经存在了。 (在程序运行前,代理对象就应经对目标对象进行了步骤的预执行代码)代码写死了.

动态代理 

动态代理: 在程序运⾏时, 运⽤反射机制动态创建⽽成。(不需要针对每个目标对象都单独创建一个代理对象)

 Java也对动态代理进⾏了实现, 并给我们提供了⼀些API, 常⻅的实现⽅式有两种:

  1. JDK动态代理
  2. CGLIB动态代理

CGLIB动态代理实现

实现步骤: 

  1. 定义⼀个类(被代理类)
  2. ⾃定义 MethodInterceptor 并重写 intercept ⽅法, intercept ⽤于增强⽬标⽅ 法,和 JDK 动态代理中的 invoke ⽅法类似
  3. 通过 Enhancer 类的 create()创建代理类

⾃定义 MethodInterceptor 

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CGLIBInterceptor implements MethodInterceptor {//⽬标对象, 即被代理对象private Object target;public CGLIBInterceptor(Object target){this.target = target;}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {// 代理增强内容System.out.println("我是中介, 开始代理");//通过反射调⽤被代理类的⽅法Object retVal = methodProxy.invoke(target, objects);//代理增强内容System.out.println("我是中介, 代理结束");return retVal;}
}

 创建代理类, 并使⽤

public class DynamicMain {public static void main(String[] args) {HouseSubject target= new RealHouseSubject();HouseSubject proxy= (HouseSubject) Enhancer.create(target.getClass(),new CGLIBInterceptor(target));proxy.rentHouse();}
}

Spring AOP 源码解析就不在进行详细解析,这东西了解就行了。

Spring对于AOP的实现,基本上都是靠 AnnotationAwareAspectJAutoProxyCreator 去完成
⽣成代理对象的逻辑在 ⽗类 AbstractAutoProxyCreator 中。

 总结

  1. AOP是⼀种思想, 是对某⼀类事情的集中处理. Spring框架实现了AOP, 称之为SpringAOP。
  2.  Spring AOP常⻅实现⽅式有两种: 1. 基于注解@Aspect来实现 2. 基于⾃定义注解来实现, 还有⼀些 更原始的⽅式,⽐如基于代理, 基于xml配置的⽅式, 但⽬标⽐较少⻅
  3. Spring AOP 是基于动态代理实现的, 有两种⽅式: 1. 基本JDK动态代理实现 2. 基于CGLIB动态代理 JDK动态代理只能代理接口,CGLIB既可以代理接口,也可以代理类. 如果是类的话一定是CGLIB代理的.  

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

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

相关文章

selenium 4.x入门篇(环境搭建、八大元素定位)

背景 Web自动化测现状 1. 属于 E2E 测试 2. 过去通过点点点 3. 好的测试&#xff0c;还需要记录、调试网页的细节 一、selenium4.x环境搭建 一键搭建 pip3 install webdriver-helper 安装后自动的完成&#xff1a; 1. 查看浏览器的版本号 2. 查询操作系统的类型…

【智能优化算法】蚱蜢优化算法(Grasshopper Optimization Algorithm,GOA)

蚱蜢优化算法(Grasshopper Optimization Algorithm&#xff0c;GOA)是期刊“IEEE Access”&#xff08;IF 3.9&#xff09;的2021年智能优化算法 01.引言 蚱蜢优化算法(Grasshopper optimization algorithm, GOA)&#xff0c;并将其应用于结构优化中的挑战性问题。该算法在数学…

Microsoft Edge浏览器:高效、简洁、个性化的网页浏览体验

Microsoft Edge是微软公司推出的一款网络浏览器&#xff0c;它是基于Chromium开源项目开发的&#xff0c;因此与Google Chrome有很多相似之处。以下是一些使用Microsoft Edge的心得体会&#xff1a; 1. 界面简洁&#xff1a;Microsoft Edge的界面设计非常简洁&#xff0c;用户…

华为od入职第13天!

今天早上就分配活了&#xff0c;写一个模块的ut&#xff0c;但是今天一句代码没写成&#xff0c;一直在看代码逻辑。下午就是新员工的一个会&#xff0c;部门20来个人做一下自我介绍啥的。晚上我导师给我们几个新员工讲项目框架和一些代码逻辑啥的&#xff0c;讲了一个多小时&a…

区块链技术与应用学习笔记(5-7节)——北大肖臻课程

​ 目录 ​BTC实现 基于交易的账本模式&#xff1a; UTXO集合&#xff1a; 交易费用&#xff1a; BTC网络 1.应用层&#xff1a; 2.网络层&#xff1a; 3传播层&#xff1a; 什么是鲁棒&#xff1f; BTC挖矿&#xff1a; 出块奖励&#xff1a; 挖矿难度调整&#…

Python | Leetcode Python题解之第51题N皇后

题目&#xff1a; 题解&#xff1a; class Solution:def solveNQueens(self, n: int) -> List[List[str]]:def generateBoard():board list()for i in range(n):row[queens[i]] "Q"board.append("".join(row))row[queens[i]] "."return b…

【C语言刷题系列】对数字添加逗号

目录 一、问题描述 二、解题思路 三、源代码 拓展&#xff1a; 个人主页&#xff1a; 倔强的石头的博客 系列专栏 &#xff1a;C语言指南 C语言刷题系列 一、问题描述 二、解题思路 题目的要求&#xff0c;即对于一个较大的整数&#xff0c;每三位数字之间添加…

CSS + HTML

目录 一.CSS&#xff08;层叠样式表&#xff09; 二. CSS 引入方式 三.选择器 3.1 标签选择器 3.2 类选择器 3.3 id选择器 3.4 通配符选择器 3.5 画盒子 四.文字控制属性 4.1字体大小 4.2字体粗细 4.3 字体倾斜 4.4行高 4.5行高--垂直居中 4.6 字体族 4.7 字体复…

使用mmdetection来训练自己的数据集(visdrone)(四)结果分析

测试 python tools/test.py <your-config-file> <your-model-weights-file> --out <save-pickle-path>关于test.py 的命令行 parser.add_argument(--out,typestr,helpdump predictions to a pickle file for offline evaluation)计算量、参数量计算脚本 pyth…

【自然语言处理】Word2VecTranE的实现

作业一 Word2Vec&TranE的实现 1 任务目标 1.1 案例简介 Word2Vec是词嵌入的经典模型&#xff0c;它通过词之间的上下文信息来建模词的相似度。TransE是知识表示学习领域的经典模型&#xff0c;它借鉴了Word2Vec的思路&#xff0c;用“头实体关系尾实体”这一简单的训练目…

【Linux】dlopen: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29‘ not found

[30116] Error loading Python lib /tmp/_MEIlvdUu6/libpython3.8.so.1.0: dlopen: /lib/x86_64-linux-gnu/libm.so.6: version GLIBC_2.29 not found (required by /tmp/_MEIlvdUu6/libpython3.8.so.1.0)1 cd到指定路径 cd /usr/local 2 下载 wget http://ftp.gnu.org/gnu/gl…

Ant Design助力:实现用户列表的优雅展示与管理

文章目录 概要前端讲解登录组件注册组件用户列表组件 后端讲解连接数据库db.js路由routes.jsexpress应用app.js 启动项目小结 概要 在上一篇博客&#x1f6aa;中&#xff0c;我们已经成功实现了登录注册系统的基本功能。现在&#xff0c;我们将进一步完善系统&#xff0c;实现…

ABAP Visual Code 新建sap系统连接

本文主要介绍如何新建SAP前端系统链接 前提是你已经都扩展完了 1.点击SAP fiori--》点击新建 2.选择 abap on premise 3.输入如下信息 4.这里介绍下URL 如何获取 SMICM-->点击service 明细里面可以看到你的host name 和 port 当然你也可以随便找一个你的odata 服务看下ur…

C++奇迹之旅:类和对象const成员static关键字友元内部类

文章目录 &#x1f4dd;const成员&#x1f320; const 成员函数是什么&#xff1f;&#x1f320; 取地址及const取地址操作符重载 &#x1f309;static成员&#x1f320;概念&#x1f320;static特性&#x1f309;static小题 &#x1f320;友元&#x1f309; 友元函数&#x1f…

标准版/开源版 移动端新增页面使用文档

在标准版开发的实际使用中&#xff0c;随着用户移动端的产品和信息内容不断增多&#xff0c;新增页面来展示对应的产品详情、模块等内容。针对一些概念或者步骤较多的内容&#xff0c;可以新增子页面构建多级模块结构&#xff0c;帮助用户快速定位。 下面就如何新增页面做一讲…

新一代大数据平台,为什么选择中国移动梧桐数据库?

个人介绍&#xff1a;艺名司镜233&#xff0c;是中国移动梧桐数据库研发团队成员&#xff0c;从事相关的技术开发近5年了。最让我觉得自豪的不是在研发这款数据库&#xff0c;而是我们用代码&#xff0c;切实地帮助企业解决数据的困扰&#xff0c;切实地解决社会的问题。 本篇文…

软件工程的介绍

软件工程 这一章的内容其实还是蛮多的,大概一共有10个章节,分别是下面的一些内容,但是呢,这一章的内容其实是比较偏向文科类的,也就是说,记忆的内容其实占有很大的篇幅,在该考试科目当中呢,其实也是主要影响上午题部分的选择题的考察,基本的分值呢,在10分左右,分值占…

Golang基础1-基本类型、if、switch、string

基本类型 bool 整数&#xff1a;byte(相当于uint8), rune(相当于int32), int/uint ,int8/uint8 ,int16/uint16 ,int32/uint32 ,int64/uint64 浮点数: float32 ,float64, complex64 ,complex128 array&#xff08;值类型&#xff09;、slice、map、chan&#xff08;引用类型…

【Android】 网络技术

前言 本文用于记录Android网络技术的使用&#xff0c; 包括我们如何发起一条HTTP请求、解析XML、JOSN格式的数据以及最好用的网络库Retrofit。 使用HTTP协议访问网络 关于HTTP协议的工作原理&#xff0c;我们只需要知道客户端向服务器发起一条HTTP请求&#xff0c;服务器接收…

【MySQL 数据宝典】【索引原理】- 001 索引原理分析 (AVL树、B-Tree、B+Tree)

一、索引定义 MySQL官方对索引定义&#xff1a;是存储引擎用于快速查找记录的一种数据结构。需要额外开辟空间和数据维护工作。 索引是物理数据页存储&#xff0c;在数据文件中&#xff08;InnoDB&#xff0c;ibd文件&#xff09;&#xff0c;利用数据页(page)存储。 索引可以…