【Spring】一文带你彻底搞懂IOC、AOP
目录
首先简单了解一下什么是spring框架
什么是IOC?
什么是依赖注入(DI)?
控制反转和依赖注入又有什么关系?
AOP是什么?
SpringAOP的实现
说了这么多抽象概念,举个实例方便理解
首先简单了解一下什么是spring框架
Spring是一个轻量级的框架,通过IOC达到松耦合的目的,使用AOP可以分离应用业务逻辑和系统服务进行内聚性的开发(不改变原有逻辑的同时对业务进行增强),不够配置各种组件的时候相对繁琐,因此后面演进除了SpringBoot框架。
使用Spring之后可以让我们不用过多关注底层的技术细节,而是更加关注业务上的逻辑的实现
什么是IOC?
Inverse of Control ——控制反转,是一种思想,这种控制反转的思想主要指的是将对象的创建、组装、管理都从代码中自己实现转移到了外部容器中来帮我们进行实现。在传统的开发方式当中,我们直接手写代码去主动创建和组装对象(将对象所需要的属性注入);在IOC思想中,这个过程被反转了,即由外部容器负责创建和管理对象。
在IOC中,我们将应用程序设计成一个个的组件,每个组件提供一定的功能,并通过接口与其他组件进行交互。通过IOC容器,我们可以把这些组件注册并配置,容器负责根据配置信息创建组件实例,并维护它们之间的依赖关系和生命周期。
什么是依赖注入(DI)?
依赖注入指的是将对象所依赖的其他对象(即依赖)注入到当前对象之中,而不是由对象自己去创建或查找他要依赖的对象。
在传统的开发方式当中,对象通过直接创建或查找依赖的对象来获取所需的依赖。
而在DI中,对象不负责创建或查找的过程,而是通过构造函数、工厂方法或属性的方式接收依赖对象。这样,依赖对象的创建和管理由外部容器负责,对象只需要专注于自身的功能实现。
依赖注入可以通过构造函数注入、setter方法注入或接口注入等方式来实现。
控制反转和依赖注入又有什么关系?
在Spring中,IOC是一种设计思想,而DI是IOC的一种具体的实现方式。实际上DI是IOC的实现技术中的一种,它通过依赖注入来实现控制反转。
IOC思想提倡将对象的设计与创建交给外部容器,并通过xml配置文件、注解、或者Java Config等方式来描述和配置对象之间的依赖关系,
Spring框架提供了一个IOC容器,即ApplicationContext,它就实现类DI的功能。在Spring中,我们可以使用XML配置文件、注解、或Java Config等方式来描述和配置对象之间的依赖关系,然后Spring容器会根据配置信息来创建对象并完成注入。
AOP是什么?
AOP即面向切面编程,可以将那些与业务不想关但是很多业务都需要调用的代码提取出来,思想就是不侵入原有代码的同时对功能进行增强。
AOP通过定义一个切面,切面可以横切到应用程序的多个模块中,并添加增强的行为。这样我们就可以将通用的功能逻辑从业务逻辑中解耦出来,提高代码的可维护性和重用性。
切面由切点(Pointcut)和通知(Advice组成)
- 切点定义的是在程序中的哪个位置进行拦截,通常使用表达式来指定匹配的连接点(join Point)
- 通知定义了要在切点执行的代码,可以在切点之前、切点之后或者周围执行特定的逻辑
- 常见的通知类包括前置通知(Before Advice)、后置通知(After Advice)、异常通知(After Throwing Advice)和环绕通知(Around Advice)等。
SpringAOP的实现
SpringAOP是基于动态代理实现的,动态代理有两种,一种是JDK动态代理,另一种是Cglib动态代理
jdk动态代理是利用反射的原理来实现的,需要调用反射包下的Proxy类的newProxyInstance方法来返回代理对象,这个方法中有三个参数,分别是用于加载代理类的类加载器、被代理类实现的接口的class数组、用于增强方法的InvocatioHandler实现类
cglib动态代理原理是利用asm开源包来实现的,是把被代理类的class文件加载进来,通过修改它的字节码生成子类来处理
jdk动态代理要求代理类必须有实现的接口,生成的动态代理类会和代理类实现同样的接口,cglib则,生成的动态代理类会继承被代理类。Spring默认使用jdk动态代理,当要被代理的类没有实现任何接口的时候采用cglib。
说了这么多抽象概念,举个实例方便理解
这是一个实现统计controller路由访问次数的代码
package com.qcby.springbootdemo.aop;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;import java.util.HashMap;
import java.util.Map;@Aspect
@Component
public class MethodCount {// 声明一个Map类型的对象,用于存储方法调用次数private Map<String, Integer> count = new HashMap<>();// 定义切点,表示拦截com.qcby.springbootdemo.Controller包下的所有方法@Pointcut("execution(* com.qcby.springbootdemo.Controller.*.*(..))")public void count() {System.out.println("切点方法执行"); //声明切点,并不会实际调用}// 环绕通知,在目标方法执行前后进行拦截@Around("count()")public Object methodExec(ProceedingJoinPoint pjp) throws Throwable {System.out.println("方法执行前");// 获取方法签名信息Signature signature = pjp.getSignature();String name = signature.getName();System.out.println(name); //-----loginSystem.out.println(signature.getDeclaringTypeName()); //---com.qcby.springbootdemo.Controller.LoginController// 获取方法参数Object[] args = pjp.getArgs();for (Object arg : args) {System.out.println("aop arg:" + arg);}Object result = null;System.out.println(signature.toLongString());System.out.println();// 统计方法调用次数,使用方法的签名作为keyString key = signature.toLongString();count.put(key, count.getOrDefault(key, 0) + 1);// 执行目标方法result = pjp.proceed();System.out.println("方法执行后");// 输出访问路由次数System.out.println(count);return result;}
}
@Aspect,表示这个类为切面类
// 定义切点,表示拦截com.qcby.springbootdemo.Controller包下的所有方法
@Pointcut("execution(* com.qcby.springbootdemo.Controller.*.*(..))")
public void count() {
System.out.println("切点方法执行"); //声明切点,并不会实际调用
}
在拦截count()方法这个切点之后,对原方法————Controller中访问路由的方法,在执行期间进行环绕,在methodExec方法中写明具体的环绕逻辑 // 环绕通知,在目标方法执行前后进行拦截 @Around("count()")
相关文章:

【Spring】一文带你彻底搞懂IOC、AOP
目录 首先简单了解一下什么是spring框架 什么是IOC? 什么是依赖注入(DI)? 控制反转和依赖注入又有什么关系? AOP是什么? SpringAOP的实现 说了这么多抽象概念,举个实例方便理解 首先简单…...

国际旅游网络的大数据分析(数学建模练习题)
题目:国际旅游网络的大数据分析 伴随着大数据时代的到来,数据分析已经深入到现代社会生活中的各个方面。 无论是国家政府部门、企事业单位还是个人,数据分析工作都是进行决策之前的 重要环节。 山东省应用统计学会是在省民政厅注册的学术类社会组织&…...

音视频技术开发周刊 | 308
每周一期,纵览音视频技术领域的干货。 新闻投稿:contributelivevideostack.com。 OpenAI首席科学家最新访谈:对模型创业两点建议、安全与对齐、Transformer够好吗? OpenAI首席科学家Ilya Sutskever最近和他的朋友Sven Strohband进…...

多旋翼飞控底层算法开发系列实验 | 多旋翼动力系统设计实验3
多旋翼动力系统设计实验3 01/多旋翼动力系统简介 多旋翼无人机的动力系统通常包括螺旋桨、电机、电调以及电池。动力系统是多旋翼最重要的组成部分,它决定了多旋翼的主要性能,如悬停时间、载重能力、飞行速度和飞行距离等。动力系统的部件…...

Redis之Sentinel(哨兵)机制
一、Sentinel是什么? Sentinel(哨岗、哨兵)是Redis的高可用性(high availability)解决方案:由一个或多个Sentinel实例(instance)组成的Sentinel系统(system)…...

加密的PDF文件,如何解密?
PDF文件带有打开密码、限制编辑,这两种密码设置了之后如何解密? 不管是打开密码或者是限制编辑,在知道密码的情况下,解密PDF密码,我们只需要在PDF编辑器中打开文件 – 属性 – 安全,将权限状态修改为无保护…...

【java】获取当前年份
目录 一、代码示例二、截图示例 一、代码示例 package com.learning;import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.Year; import java.util.Calendar; import java.util.Date;/*** 获取当前年份*/ public class GetCurrentYear {public …...

前端面试话术集锦第一篇
🚗前端面试集锦目录 💖前端面试话术集锦第一篇💖 💖前端面试话术集锦第二篇💖 文章目录 1. 前端需要注意哪些SEO2. \<img>的title和alt有什么区别3. HTTP的⼏种请求⽅法⽤途4. 从浏览器地址栏输⼊url到显示⻚⾯的步骤5. 如何进⾏⽹站性能优化6. HTTP状态码及其…...

NeRFMeshing - 精确提取NeRF中的3D网格
准确的 3D 场景和对象重建对于机器人、摄影测量和 AR/VR 等各种应用至关重要。 NeRF 在合成新颖视图方面取得了成功,但在准确表示底层几何方面存在不足。 推荐:用 NSDT编辑器 快速搭建可编程3D场景 我们已经看到了最新的进展,例如 NVIDIA 的 …...

后端面试话术集锦第五篇:rabbitmq面试话术
🚗后端面试集锦目录 💖后端面试话术集锦第 1 篇:spring面试话术💖 💖后端面试话术集锦第 2 篇:spring boot面试话术💖 💖后端面试话术集锦第 3 篇:spring cloud面试话术💖 💖后端面试话术集锦第 4 篇:ElasticSearch面试话术💖 💖后端面试话术集锦第 5 …...

Spring Boot(Vue3+ElementPlus+Axios+MyBatisPlus+Spring Boot 前后端分离)【一】
😀前言 本篇博文是关于Spring Boot(Vue3ElementPlusAxiosMyBatisPlusSpring Boot 前后端分离)【一】,希望你能够喜欢 🏠个人主页:晨犀主页 🧑个人简介:大家好,我是晨犀,希望我的文章…...

vue3之reactive和ref学习篇
<script lang"ts" setup> // reactive参数必须为引用类型 和ref简单类型或者引用类型 import { reactive, ref } from vue; const arr reactive([10]) const count ref(0); let increasing true; console.log(count) const change ()>{if(increasing){c…...

【推荐】Spring与Mybatis集成整合
目录 1.概述 2.集成 2.1代码演示: 3.整合 3.1概述 3.2 进行整合分页 接着上两篇,我已经写了Mybatis动态之灵活使用,mybatis的分页和特殊字符的使用方式接下来把它们集成起来,是如何的呢👇👇…...

listdir, makedirs, shuffle, exists, webdriver.Chrome, roll方法快速查阅
1 os.listdir() os.listdir() 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表。 2 os.makedirs(path) 方法用于递归创建目录。 如果子目录创建失败或者已经存在,会抛出一个 OSError 的异常 3 numpy.random.shuffle(x) 由numpy.random调用,可…...

java.nio.ByteBuffer 学习笔记
目录 java 重复使用bytebuffer例子: java验证flip函数: flip讲解 以下内容转自: java.nio.ByteBuffer java 重复使用bytebuffer例子: import java.nio.ByteBuffer;public class ByteBufferExample {public static void main…...

自动化实时在线静电监控系统的构成
自动化实时在线静电监控系统是一种帮助企业监测和管理静电问题的技术解决方案。静电在许多工业和商业环境中都是一个潜在的风险和生产问题。通过使用这样的监控系统,企业可以及时发现并采取对策来预防或减轻可能的静电问题。 该系统通常由以下组成部分构成…...

Windows 转 mac 记录
初次从Windows转mac可能会不适应,建议先看看 【6分钟搞定MacBook】不懂时无所适从,学会后越用越爽!_哔哩哔哩_bilibili 我主要是做一些补充记录 1、Windows的右键等于mac的双击触控板、control单击触控板 2、运行中的应用下方会有一个点&…...

Linux_4_文本处理工具和正则表达式
目录 1文本编辑工具之神VIM1.1 vi和vim简介1.2使用vim1.2.1 vim 命令格式1.2.2三种主要模式和转换 1.3扩展命令模式1.3.1扩展命令模式基本命令1.3.2 地址定界1.3.3查找并替换1.3.4定制vim的工作特性1.3.4.1行号1.3.4.2忽略字符的大小写1.3.4.3白动缩进1.3.4.4复制粘贴保留格式1…...

[Unity]VSCode无代码提示
查看vscode的output窗口,提示加载 csproj 文件失败 It need be converted to new SDK style to work in C# Dev Kit. 把unity的PackageManager里的 Visual Studio Editor 版本升级到2.0.20或以上,重新生成csproj文件就好了。 参考vscode官方ÿ…...
画流程图都可以用哪些工具?
在日常生活中,我相信我们很多人都看到过流程图。对于设计师来说,它还需要涉及流程图来反映用户的旅程和交互方式。那么你知道哪些流行的流程图设计软件呢?作为高级设计师,我今天推荐10款流程图设计软件。你可以和我一起读这篇文章…...

Elasticsearch中倒排索引、分词器、DSL语法使用介绍
🍓 简介:java系列技术分享(👉持续更新中…🔥) 🍓 初衷:一起学习、一起进步、坚持不懈 🍓 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正🙏 🍓 希望这篇文章对你有所帮助,欢…...

rabbitmq笔记-rabbitmq进阶-数据可靠性,rabbitmq高级特性
消息何去何从 mandatory和immediate是channel.basicPublish方法的两个参数,都有消息传递过程中不可达目的地时将消息返回给生产者的功能。 mandatory参数 true:交换器无法根据自身的类型 和路由键找到符合条件的队列,rabbitmq调用Basic.Re…...

【笔记】判断两个String字符串是否相同(考虑字符串为null的情况)
判断两个字符串是否相同,可用于判断一个字段在逻辑处理前后,值是否有变化。 其中重点是要考虑两个字符串是否有为null的情况,如果其中一个,或者两个都为空,用str1.equals(str2)直接判断,就会报NullPointer…...

【校招VIP】java语言考点之多线程NIO
考点介绍 多线程&NIO考点是校招面试中的常制点之一。 Java NIO是new IO的简称,是一种可以替代Java 10的一套新的IO机制。它提供了一套不同于Java标准1O的操作机制,严格来说,NIO与并发并无直接关系,但是使用NIO技术可以大大提高…...

JVM知识点(一)
1、JVM基础概念 (1)JVM、JRE、JDK JRE:JVM基本类库组成的运行环境就是JRE。JVM自己是无法完成一次编译,处处运行的,需要有一个基本类库告诉JVM如何操作运行,如如何操作文件,连接网络等&#x…...

网页接口导入postman进行接口请求
postman版本:v10.17.4 一、拷贝接口信息 网页打开开发者工具-networkk,在网页上请求一次接口,鼠标指在接口上,点击鼠标右键-copy-copy as cURL(bash) 二、导入postman 打开postman,点击import-Raw text,…...

【Leetcode】124.二叉树中的最大路径和(Hard)
一、题目 1、题目描述 二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。 路径和 是路径中各节点值的总和。 给你一个二叉树的根节点 root ,返回其…...

django自动创建model数据
目前使用的环境:django4.2.3,python3.10 django通过一些第三方库,可以轻易的自动生成一系列的后台数据。 首先先创建一个数据库: 然后,在setting.py中就可以指定我们新创建的数据库了。 DATABASES {default: {ENGI…...

vscode 远程连接
这里记录的是修改ssh配置文件的方式远程连接服务器中的docker服务器 假如已经创建好了docker,并已经启动 1. config ssh in dev container 在/etc/ssh/sshd_config中修改 PermitRootLogin in 把 PermitRootLogin prohibit-password 修改为 PermitRootLogin yes …...

Error running ‘Tomcat 8.5.29‘ Address localhost:1099 is already in use
一、Error running ‘Tomcat 8.5.29’ Address localhost:1099 is already in use 原因:端口1099被占用了。 二、解决 2.1 解决方法一-结束该端口1099占用 //1-查看端口占用,根据端口号1099,获取PID(进程ID) netstat -ano | findstr "…...