IOC 和 AOP

IOC

所谓的IOC(inversion of control),就是控制反转的意思。何为控制反转?

在传统的程序设计中,应用程序代码通常控制着对象的创建和管理。例如,一个对象需要依赖其他对象,那么它会直接new出来对象。这样的设计通常被称为 "控制流程"。

而在IOC 中,控制关系发生了反转。控制权被转移到Spring容器中,容器负责创建和管理对象,并在需要的时候将它们注入到应用程序中。

所以,原来这个对象的控制权在我们的代码中,我们自己new的对象,在Spring中,应用程序不再控制对象的创建,而是被动地接受由容器注入的对象。

我们拿代码来举个例子:

下面是一个没有IOC的例子

class A {}
class B {

    // B需要将A的实例new出来,也就是我们说的控制
    private A a = new A();

    public void use() {
        System.out.print(a);
    }
        
}

当有了IOC之后

@Component // 说明A自己控制自己,把自己初始化出来,注入给了容器
class A {}

class B {

    // B不需要控制a,直接使用。如果A没有把自己注入给容器,B就不能使用
    @Resource
    private A a;

    public void use() {
        System.out.print(a);
    }
        
}

也就是说,没有Spring的话,我们要使用的对象,需要我们自己创建,而有了Spring的IOC之后,对象由IOC容器创建并管理,我们只需要在想要使用的时候从容器中获取就行了。

值得说明的是,IOC只是一种思想和理念,可以有不同的实现方式。

IOC的优点

使用IOC,有最少三个好处:

  1. 使用者不用关心引用bean的实现细节,譬如对于B b = new A(c,d,e,f);来说,如果B要使用A,那还要把c,d,e,f多个类全都感知一遍,这显然是非常麻烦且不合理的

  1. 不用创建多个相同的bean导致浪费,仍然是:
A b = new A();
A z = new A();

如果B和Z都引用了A,那么B和Z就可能new 两个A实例,实际上,我们只需要一个就好了。

  1. Bean的修改使用方无需感知。同样是上面的例子,假如说BeanA需要修改,如果没有IOC的话,所有引用到A的其他bean都需要感知这个逻辑,并且做对应的修改。但是如果使用了IOC,其他bean就完全不用感知到

Spring的IOC

对于Spring的IOC来说,它是IOC思想的一种实现方式。在容器启动的时候,它会根据每个bean的要求,将bean注入到SpringContainer中。如果有其他bean需要使用,就直接从容器中获取即可,如下图所示:

扩展知识

IOC是如何实现的?

使用Spring的IOC容器能力,非常简单,如下代码所示:

ApplicationContext context= new AnnotationConfigApplicationContext("cn.wxxlamp.spring.ioc");
Bean bean = context.getBean(Bean.class);
bean.use();

从上面的代码中,我们也能看出来Spring的IOC是如何实现的:

  1. 从配置元数据中获取要DI的业务POJO(这里的配置元数据包括xml,注解,configuration类等)
  2. 将业务POJO形成BeanDefinition注入到Spring Container中
  3. 使用方通过ApplicationContext从Spring Container直接获取即可。如下图所示:

AOP

AOP(Aspect-Oriented Programming),即面向切面编程,用人话说就是把公共的逻辑抽出来,让开发者可以更专注于业务逻辑开发。

和IOC一样,AOP也指的是一种思想。AOP思想是OOP(Object-Oriented Programming)的补充。OOP是面向类和对象的,但是AOP则是面向不同切面的。一个切面可以横跨多个类和对象去操作,极大的丰富了开发者的使用方式,提高了开发效率。

譬如,一个订单的创建,可能需要以下步骤:

  1. 权限校验
  2. 事务管理
  3. 创建订单
  4. 日志打印

如果使用AOP思想,我们就可以把这四步当成四个“切面”,让业务人员专注开发第三个切面,其他三个切面则是基础的通用逻辑,统一交给AOP封装和管理。

Spring AOP有如下概念(列举下,不用刻意记):

术语

翻译

释义

Aspect

切面

切面由切入点和通知组成,它既包含了横切逻辑的定义,也包括了切入点的定义。切面是一个横切关注点的模块化,一个切面能够包含同一个类型的不同增强方法,比如说事务处理和日志处理可以理解为两个切面。

PointCut

切入点

切入点是对连接点进行拦截的条件定义,决定通知应该作用于截哪些方法。(充当where角色,即在哪里做)

Advice

通知

通知定义了通过切入点拦截后,应该在连接点做什么,是切面的具体行为。(充当what角色,即做什么)

Target

目标对象

目标对象指将要被增强的对象,即包含主业务逻辑的类对象。或者说是被一个或者多个切面所通知的对象。

JoinPoint

连接点

连接点是程序在运行时的执行点,这个点可以是正在执行的方法,或者是正在抛出的异常。因为Spring只支持方法类型的连接点,所以在Spring中连接点就是运行时刻被拦截到的方法。连接点由两个信息确定:

  • 方法(表示程序执行点,即在哪个目标方法)
  • 相对点(表示方位,即目标方法的什么位置,比如调用前,后等)

Weaving

织入

织入是将切面和业务逻辑对象连接起来, 并创建通知代理的过程。织入可以在编译时,类加载时和运行时完成。在编译时进行织入就是静态代理,而在运行时进行织入则是动态代理。

对于通知类型来说:

Before Advice

连接点执行前执行的逻辑

After returning advice

连接点正常执行(未抛出异常)后执行的逻辑

After throwing advice

连接点抛出异常后执行的逻辑

After finally advice

无论连接点是正常执行还是抛出异常,在连接点执行完毕后执行的逻辑

Around advice

该通知可以非常灵活的在方法调用前后执行特定的逻辑

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

express+mysql+vue,从零搭建一个商城管理系统6--数据校验和登录

提示:学习express,搭建管理系统 文章目录 前言一、修改models/user.js二、修改routes下的user.js三、Api新建user/login接口四、删除数据库原有数据,添加新验证规则的用户四、用户登录总结 前言 需求:主要学习express,…

【Linux】基础篇-Linux四种环境搭建的方式(详细安装说明步骤,搭载下载安装地址)

目录 1. 使用虚拟机(推荐VMware)centos 7版本 1.1VMware虚拟机下载 1.2VMware 安装 1.3centos-7 清华大学镜像下载 1.4 centos-7 清华大学镜像导入虚拟机VMware 2.使用虚拟机ubuntu 20.04版本 2.1虚拟机下载同上 2.2虚拟机安装同上 2.3ubunt…

ROS-Ubuntu 版本相关

ROS-Ubuntu 版本相关:安装指引 年代ROS1版本Ubuntu 版本2014Indigo14.042016Kinetic16.042018Melodic18.042020Noetic20.04 & 22.04 ROS2兼顾了工业使用上的问题。 年代ROS2版本Ubuntu 版本2022Humble20.04 & 22.042023Iron16.04 相关参考: […

【Qt 学习之路】使用 cmake 在Windows上 编译 ZeroMQ

文章目录 1、概述2、编译2.1、用 Visual Studio 的解决方案方式2.1.1、找到 Builds 文件夹2.1.2、查看 deprecated-msvc 下的 libzmq.sln 文件2.1.3、使用 Visual Studio 打开 libzmq.sln 解决方案2.1.4、修改 libzmq.import.props 文件2.1.5、编译生成 2.2、用 C 的cmake方式2…

【前端入门】设计模式+单多页+React

设计模式是一种解决特定问题的经验总结,它提供了经过验证的解决方案,可以在软件开发过程中使用。设计模式可以帮助前端开发人员更有效地组织和管理代码,并提供一种共享的语言和框架,以便与其他开发人员进行交流。 以下是一些常见…

十二、Qt自定义Widget组件、静态库与动态库

一、自定义Widget组件 1、自定义Widget组件 使用步骤采用提升法(promotion)重新定义paintEvent事件 2、实现程序 (1)创建项目,基于QWidget (2)添加类,为Widget组件提升类 #inclu…

Delegate(P29 5.5delegate)

一、Delegate简介 每个代理都可以访问许多附加的属性,其中一些来自数据模型,另一些来自视图。 从模型中(Model):属性将每个项目的数据传递给 delegate。 从视图中(View):属性将状…

dcat admin 自定义页面

自定义用户详情页 整体分为两部分:用户信息、tab框 用户信息采用自定义页面加载,controller代码如下: protected function detail($id) {return Show::make($id, GameUser::with(finance), function (Show $show) {// 这段就是加载自定义页面…

pdf怎么合并在一起?

pdf怎么合并在一起?在日常工作和学习中,我们常常需要处理大量的PDF文件。有时候,我们可能希望将多个PDF文件合并成一个文件,以便于管理和分享。这时候,PDF文件合并工具就能派上用场了。PDF文件合并是一种将多个PDF文件…

MySQL 事务原理分析

事务 前提:有并发连接。定义:事务是用户定义的一系列操作,这些操作要么都做,要么都不做,是一个不可分割的单位。目的:事务将数据库从一种一致性状态转换为另一种一致性状态,保证系统始终处于一…

【数据结构】从链表到LinkedList类

🧧🧧🧧🧧🧧个人主页🎈🎈🎈🎈🎈 🧧🧧🧧🧧🧧数据结构专栏🎈🎈🎈&…

NerfStudio安装及第一个场景重建

NerfStudio文档是写在windows和linux上安装,本文记录Linux安装的过程,且我的cuda是11.7 创建环境 conda create --name nerfstudio -y python3.8 conda activate nerfstudio python -m pip install --upgrade pip Pytorch要求2.0.1之后的,文档推荐cud…

JavaWeb——005 请求响应 分层解耦(Postman、三层架构、IOC、DI、注解)

SpringBootWeb请求响应 这里写目录标题 SpringBootWeb请求响应前言1. 请求1.1 Postman1.1.1 介绍1.1.2 安装 1.2 简单参数1.2.1 原始方式1.2.2 SpringBoot方式1.2.3 参数名不一致 1.3 实体参数1.3.1 简单实体对象1.3.2 复杂实体对象 1.4 数组集合参数1.4.1 数组1.4.2 集合 1.5 …

产品老化试验目的、用途

什么是老化试验? 老化试验是通过模拟产品在使用过程中的老化情况,来评估产品在长期使用后的性能和可靠性。这种测试可以帮助制造商了解产品的寿命和耐久性,以及产品在不同环境条件下的表现。 模拟量采集/老化房采集软件 为什么需要进行老化试…

【Leetcode每日一刷】贪心算法01:455.分发饼干、376. 摆动序列、53. 最大子序和

博主简介:努力学习和进步中的的22级计科生博主主页: Yaoyao2024每日一句: “ 路虽远,行则将至。事虽难,做则可成。” 文章目录 前言:贪心算法一、455.分发饼干二、376. 摆动序列三、53. 最大子序和 前言:贪…

挑战杯 基于机器视觉的图像拼接算法

前言 图像拼接在实际的应用场景很广,比如无人机航拍,遥感图像等等,图像拼接是进一步做图像理解基础步骤,拼接效果的好坏直接影响接下来的工作,所以一个好的图像拼接算法非常重要。 再举一个身边的例子吧,…

信号系统之切比雪夫过滤器

1 切比雪夫和巴特沃斯的响应 切比雪夫响应是一种数学策略,通过允许频率响应中的纹波来实现更快的滚降。使用这种方法的模拟和数字滤波器称为切比雪夫滤波器。这些滤波器因使用切比雪夫多项式而得名,切比雪夫多项式由俄罗斯数学家帕夫努蒂切比雪夫&#…

基于FPGA的9/7整数小波变换和逆变换verilog实现,包含testbench

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 9/7整数小波变换原理 4.2 逆变换过程 5.算法完整程序工程 1.算法运行效果图预览 将测试结果导入到matlab显示 2.算法运行软件版本 vivado2019.2,matlab2022a 3.部分核心程…

寒假作业Day 01

这个项目主要是为了复习博主之前关于C语言和数据结构的寒假作业,大家也可以根据这些题目自己进行填写并检查自己的知识点是否过关 博主也会有错误,所以如果大家看到错误,也希望大家能够进行指正,谢谢大家! Day 01 一…

静态链表(1)

什么叫静态链表?——用顺序表模拟链表,就叫做静态链表 第一列相当于数据域data,第二列相当于指针域next, 第一行(0)相当于头结点(头结点的数据域不放数据) (a&#xff…