【Spring】(一)Spring设计核心思想

文章目录

  • 一、初识 Spring
    • 1.1 什么是 Spring
    • 1.2 什么是 容器
    • 1.3 什么是 IoC
  • 二、对 IoC 的深入理解
    • 2.1 传统程序开发方式存在的问题
    • 2.2 控制反转式程序的开发
    • 2.3 对比总结
  • 三、对 Spring IoC 的理解
  • 四、DI 的概念
    • 4.1 什么是 DI
    • 4.2 DI 与 IoC的关系


一、初识 Spring

1.1 什么是 Spring

Spring 是一个开源的轻量级 Java 框架,旨在简化 Java 应用程序的开发。它提供了一个全面的编程和配置模型,用于构建各种类型的应用,包括企业级应用和独立的 Java 应用。Spring 的设计理念是基于依赖注入(Dependency Injection)和面向切面编程(Aspect-Oriented Programming),使得应用开发更加模块化、灵活和易于维护

用一句话概括 Spring 就是:Spring 是一个包含了众多工具的 IoC 容器

1.2 什么是 容器

所谓容器就是能够盛放东西的器皿,就好像水杯一样。而 Spring 就是一个容器,它的功能就是负责存储和管理应用中的各个组件(Bean),然后在使用的时候从 Spring 中取出需要的 Bean 对象。

1.3 什么是 IoC

IoC,即控制反转(Inversion of Control),是 Spring 框架的核心理念之一。它将应用程序的控制权从开发人员的手中反转,由 Spring 容器负责管理对象的生命周期以及依赖关系。在传统的程序设计中,开发人员需要负责手动创建和管理对象,但是在 IoC 容器中,开发人员只需要定义组件(Bean)的配置元数据,由容器负责实例化、装配和管理这些组件

二、对 IoC 的深入理解

如果初次理解 IoC,可能会觉得很困难,可以通过下面的例子帮助我们理解 IoC 的作用。

假如,现在需要使用程序来模拟一个简单制造汽车的过程,其实现思路如下:

  • 如果要造汽车Car,首先需要有车身Framework;
  • 如果需要造车身Framework,首先就需要有地盘Bottom;
  • 如果需要造地盘Bottom,首先就需要有轮子Tire。

上述过程,不难发现存在一个依赖链的关系,首先通过传统程序的开发方式,来感受一下其存在的问题。

2.1 传统程序开发方式存在的问题

下面是用传统方式编写的代码:

class Tire {private Integer size = 17;public void init(){System.out.println("do tire: size = " + size);}
}class Bottom {private Tire tire;public Bottom(){this.tire = new Tire();}public void init(){tire.init();System.out.println("do bottom");}
}class Framework {private Bottom bottom;public Framework(){bottom = new Bottom();}public void init(){bottom.init();System.out.println("do framework");}
}class Car {private Framework framework;public Car(){framework = new Framework();}public void init(){framework.init();System.out.println("do car");}
}public class Tradition {public static void main(String[] args) {Car car = new Car();car.init();}
}

在上面的传统写法中,可以发现每个类之间的耦合度非常高,并且每个类都需要管理它所依赖的对象,即掌握着其依赖对象的控制权。此时如果用户的需求改变了,使用的轮子Tire不再是固定的尺寸,而是需要由用户自己输入尺寸的大小,此时Tire类的代码需要更改为:

class Tire {private Integer size = 17;public Tire(int size){this.size = size;}public void init(){System.out.println("do tire: size = " + size);}
}

此时发现,不改不要紧,但是一改问题就来了,由于各个类之间的高耦合性,使得后续所依赖前者的代码都需要进行修改。


class Bottom {private Tire tire;public Bottom(int size){this.tire = new Tire(size);}public void init(){tire.init();System.out.println("do bottom");}
}class Framework {private Bottom bottom;public Framework(int size){bottom = new Bottom(size);}public void init(){bottom.init();System.out.println("do framework");}
}class Car {private Framework framework;public Car(int size){framework = new Framework(size);}public void init(){framework.init();System.out.println("do car");}
}

如果要后续要继续增加 Tire 类的属性,例如color,此时就还要需要从头来进行修改。那么如何解决这个缺陷呢?

上次代码出现这个缺陷的根本原因就在于:当前类将自己所依赖的类的控制权掌握在了自己的手中,即在自己类的内部调用的所依赖类的构造方法。因此解决这个问题的方法也非常简单,那就是不在自己的内部代码中创建所依赖的对象,而是通过参数传递的方式获取这个依赖对象,这就是控制权转移的思想,即 IoC。

2.2 控制反转式程序的开发

下面是转移控制权的代码写法,即将当前类所依赖的对象通过参数的方式进行传入:

class Tire {private Integer size = 17;public Tire(int size) {this.size = size;}public void init() {System.out.println("do tire: size = " + size);}
}class Bottom {private Tire tire;public Bottom(Tire tire) {this.tire = tire;}public void init() {tire.init();System.out.println("do bottom");}
}class Framework {private Bottom bottom;public Framework(Bottom bottom) {this.bottom = bottom;}public void init() {bottom.init();System.out.println("do framework");}
}class Car {private Framework framework;public Car(Framework framework) {this.framework = framework;}public void init() {framework.init();System.out.println("do car");}
}public class IoC {public static void main(String[] args) {Tire tire = new Tire(18, "red");Bottom bottom = new Bottom(tire);Framework framework = new Framework(bottom);Car car = new Car(framework);car.init();}
}

此时,如果用户需求又发生了改变,要求轮子 Tire 的颜色也要自己来挑选,此时更改的代码如下:

class Tire {private Integer size = 17;private String color;public Tire(int size, String color) {this.size = size;this.color = color;}public void init() {System.out.println("do tire: size = " + size + ", color = " + color);}
}

此时,只需要修改 Tire 类和创建 Tire 对象的代码,而不需要对其他代码进行修改。可以发现,即使底层类的改变也不会影响到整个调用链的改变,这样就实现了代码的解耦,从而实现了更加灵活、通用的程序设计方式。

2.3 对比总结

以下是传统代码和 IoC 形式代码的调用过程:

通过对比两种代码的实现方式不难发现:

  1. 两种代码中类的创建顺序是相反的:
    • 传统代码的创建顺序是由顶层 Car 类创建到底层 Tire 类,即:Car -> Framework -> Bottom -> Tire
    • 而 IoC 形式代码的创建顺序则是由底层 Tire 类创建到顶层 Car 类,即:Tire -> Bottom -> Frame -> Car
  2. 传统代码中,当前类掌握着自己所依赖对象的控制权,耦合度非常高,一旦底层代码修改了,整个调用链的代码都会修改
  3. IoC 形式的代码中,当前类通过参数传递的方式,将对所依赖对象的控制权进行反转,即不再有自己掌控,此时无论底层代码如何修改,也不会对整个调用链上的代码造成影响

三、对 Spring IoC 的理解

“Spring 是一个 包含众多工具的 IoC 容器” 这句话的理解非常重要,因为它揭示了 Spring 框架最核心的功能和优势。在这里,我们可以把 Spring IoC 容器比喻成一个大大的容器,用来存放应用程序中的各种对象(Bean)。这个容器不仅负责对象生命周期的管理,还实现了对象之间的依赖注入(DI),从而实现了控制反转。

既然 Spring 是容器,那么它的核心功能就可以分为两个:

1. 将对象存入容器

  • 程序员首先需要创建应用程序中的各种对象(Bean),这些对象代表应用程序中的不同组件和功能模块。
  • 然后通过配置文件(如XML、注解或者 Java 配置类)告诉 Spring IoC 容器如何创建这些对象,以及它们之间的依赖关系。
  • Spring IoC 容器会根据配置信息,在应用程序启动的时候负责实例化这些对象并存放到容器中,从而完成对象的创建和组装过程。

2. 从容器中取出对象

  • 一旦对象被存入了 Spring IoC 容器中,它们就可以在应用程序的其他部分被获取和使用。程序员不需要显示地创建对象,而是从 Spring 容器中直接获取已经创建好的对象来使用。
  • 通过依赖注入的方式,Spring IoC 容器会在合适的时候将依赖的对象自动注入到需要它们的地方。

总的来说,Spring IoC 容器负责管理对象的创建、组装和依赖关系,开发人员只需关注对象的定义和配置通过将对象存入容器并从容器中获取对象,Spring 实现了对象的控制反转,使得应用程序的开发更加简洁、灵活和易于维护。这也是 Spring 框架的核心之一,为开发者提供了一个强大且高度可定制的开发平台。

四、DI 的概念

4.1 什么是 DI

依赖注入(Dependency Injection,DI)是一种实现 IoC 的具体技术,它是 IoC 容器的一种表现形式。在 DI 中,对象之间的依赖关系不再有类自己创建和管理,而是有外部容器(如 Spring)来负责注入依赖的对象。简单来说,DI 就是将一个对象的依赖关系交给外部容器来处理,从而实现对象之间的解耦。

在 DI 中,通常由三种注入方式:

  1. 构造方法注入(Constructor Injection):通过构造函数接收依赖对象,这是最常见的注入方式。
  2. Setter 方法注入(Setter Injection):通过Setter方法设置依赖对象。
  3. 属性注入(Field Injection):通过属性的方式注入依赖对象。

DI 使得对象的依赖关系从代码中移出,变得可配置和灵活。通过使用DI,我们可以在应用程序的不同部分之间实现松耦合,提高代码的可测试性、可维护性和可扩展性。

4.2 DI 与 IoC的关系

DI(依赖注入)和 IoC(控制反转)是紧密相关的概念,通常同时被提及,它们之间的关系可以概括为:

  • IoC 是一种设计思想,它将应用程序的控制权从代码内部转移到外部容器。通过 IoC,对象的创建和依赖关系的管理被反转,交由容器来负责管理,而不是由代码显示的控制。
  • DI 是实现 IoC 的一种具体技术手段,它是 IoC 的一种表现形式。通过 DI,对象之间的依赖关系由外部容器来注入,而不是由对象自己来创建和管理依赖。

因此,DI 是 IoC 的一部分,它是实现 IoC 的重要手段。Spring 框架正是以 IoC 和 DI 为核心,提供了强大的 IoC 容器和依赖注入机制,从而实现了各种功能,如依赖管理、AOP、事务管理等。通过 IoC 和 DI,Spring 框架实现了松耦合、可配置和可扩展的应用程序开发。

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

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

相关文章

Mermaid系列之FlowChart流程图

一.欢迎来到我的酒馆 介绍mermaid下,Flowchat流程图语法。 目录 一.欢迎来到我的酒馆二.什么是mermiad工具三.在vs code中使用mermaid四.基本语法 二.什么是mermiad工具 2.1 mermaid可以让你使用代码来创建图表和可视化效果。mermaid是一款基于javascript语言的图表…

宝塔面板点击SSL闪退打不开怎么解决?

宝塔Linux面板点击SSL证书闪退如何解决?旧版本的宝塔Linux面板确实存在这种情况,如何解决?升级你的宝塔Linux面板即可。新手站长分享宝塔面板SSL闪退的解决方法: 宝塔面板点击SSL证书闪退解决方法 问题:宝塔Linux面板…

谈谈网络安全

目录 1.概念 2.发展现状 3.主要问题 1.概念 网络安全是指保护计算机网络和其中的数据免受未经授权访问、损坏、窃取或破坏的过程和技术。网络安全涉及预防和检测潜在的威胁和漏洞,并采取措施保护网络的机密性、完整性和可用性。 网络安全的概念包括以下几个方面&am…

vue2 todoapp案例(静态)

1.创建三个子组件(TodoHeader、TodoMain、TodoFooter)和两个(index.css、base.css)样式&#xff1b; TodoHeader页面 <template><header class"header"><h1>todos</h1><input id"toggle-all" class"toggle-all" typ…

【力扣】链表题目总结

文章目录 链表基础题型一、单链表翻转、反转、旋转1.反转链表2.反转链表II——反转部分链表3.旋转链表4.K个一组翻转链表5.反转偶数长度组的节点 二、删除单链表中的结点1.删除链表的结点2.删除未排序链表中的重复节点3.删除已排序链表中的重复元素I——重复元素只剩下一个4.删…

【ASP.NET MVC】第一个登录页面(8)

一、准备工作 先从网上&#xff08;站长之家、模板之家&#xff0c;甚至TB&#xff09;下载一个HTML模板&#xff0c;要求一整套的CSS和必要的JS&#xff0c;比如下图&#xff1a; 登录页面的效果是&#xff1a; 首页&#xff1a; 利用这些模板可以减少前台网页的设计——拿来…

vue+element中如何设置单个el-date-picker开始时间和结束时间关联

功能&#xff1a;选了开始时间&#xff0c;则结束时间只能选择开始时间之后的&#xff1b;选了结束时间&#xff0c;则开始时间只能选择结束时间之前的 重点是picker-options属性 图示&#xff1a; 代码展示: // body 内部<el-form-item><el-date-pickerv-model&qu…

Qt+联想电脑管家

1.自定义按钮类 效果&#xff1a; (1)仅当未选中&#xff0c;未悬浮时 (2)其他三种情况&#xff0c;均如图 #ifndef BTN_H #define BTN_H#include <QPushButton> class btn : public QPushButton {Q_OBJECT public:btn(QWidget * parent nullptr);void set_normal_icon(…

02_kafka_基本概念_基础架构

文章目录 常见的消息队列工作模式基本概念kafka 特性Kafka 基本架构topic 分区的 目的/ 好处 日志存储形式消费者&#xff0c;消费方式 逻辑消费组 高性能写入&#xff1a; 顺序写 mmap读取&#xff1a;零拷贝DMA 使用场景 常见的消息队列工作模式 至多一次&#xff1a;消息被…

pytorch实战-图像分类(二)(模型训练及验证)(基于迁移学习(理解+代码))

目录 1.迁移学习概念 2.数据预处理 3.训练模型&#xff08;基于迁移学习&#xff09; 3.1选择网络&#xff0c;这里用resnet 3.2如果用GPU训练&#xff0c;需要加入以下代码 3.3卷积层冻结模块 3.4加载resnet152模 3.5解释initialize_model函数 3.6迁移学习网络搭建 3.…

UE4/5 GAS技能系统入门2 - AttributeSet

在GAS系统中对属性进行修改需要用到GE&#xff08;Gameplay Effect&#xff09;&#xff0c;而这又涉及到AttributeSet这样的概念。 AttributeSet用于描述角色的属性集合&#xff0c;如攻击力、血量、防御力等&#xff0c;与GAS系统整合度较高&#xff0c;本文就来讲一讲Attri…

Consul屏蔽api

consul 没有设置密码 需要屏蔽api&#xff1a;/v1/internal/ui/nodes?dc&token 防止信息泄露 配置config.json {"http_config": {"block_endpoints": ["/v1/internal/ui/nodes"]} }启动consul时使用该配置&#xff1a; consul agent -de…

Java实现Google cloud storage 文件上传,Google oss

storage 控制台位置 创建一个bucket 点进bucket里面&#xff0c;权限配置里&#xff0c;公开访问&#xff0c;在互联网上公开&#xff0c;需要配置角色权限 新增一个访问权限 &#xff0c;账号这里可以模糊搜索&#xff0c; 角色配置 给allUser配置俩角色就可以出现 在互联…

0.CLIP

目录 前言背景缘起/摘要数据集拟解决问题 精读IntroductionModel2.1自然语言监督2.2 创建一个有效的大数据集选择一个有效的预训练方法2.4 选择模型&#xff08;选择Encoder&#xff09;2.5训练小结 实验 复现&#xff08;略&#xff09; 前言 本课程来自深度之眼《多模态》训…

R语言3_安装SeurateData

环境Ubuntu22/20, R4.1 在命令行中键入&#xff0c; apt-get update apt install libcurl4-openssl-dev libssl-dev libxml2-dev libcairo2-dev libgtk-3-dev # libcairo2-dev :: systemfonts # libgtk :: textshaping进入r语言交互环境&#xff0c;键入&#xff0c; instal…

Mac显示隐藏文件夹

1、设置隐藏文件可见 defaults write com.apple.finder AppleShowAllFiles TRUE 2、killall Finder killall Finder

QtWebApp开发https服务器,完成客户端与服务器基于ssl的双向认证,纯代码操作

引言&#xff1a;所谓http协议&#xff0c;本质上也是基于TCP/IP上服务器与客户端请求和应答的标准&#xff0c;web开发中常用的http server有apache和nginx。Qt程序作为http client可以使用QNetworkAccessManager很方便的进行http相关的操作。Qt本身并没有http server相关的库…

深度学习——全维度动态卷积ODConv

ODConv(OMNI-DIMENSIONAL DYNAMIC CONVOLUTION)是一种关注了空域、输入通道、输出通道等维度上的动态性的卷积方法&#xff0c;因此被称为全维度动态卷积。 part1. 什么是动态卷积 动态卷积就是对卷积核进行线性加权 第一篇提出动态卷积的文章也是在SE之后&#xff0c;他提出…

快速排序【Java算法】

文章目录 1. 概念2. 思路3. 代码实现 1. 概念 快速排序是一种比较高效的排序算法&#xff0c;采用 “分而治之” 的思想&#xff0c;通过多次比较和交换来实现排序&#xff0c;在一趟排序中把将要排序的数据分成两个独立的部分&#xff0c;对这两部分进行排序使得其中一部分所有…

Flask项目打包为exe(附带项目资源,静态文件)

1.在项目根目录创建my_app.spec文件&#xff0c;内容如下&#xff1a; # -*- mode: python ; coding: utf-8 -*-block_cipher Nonea Analysis([server.py], # flask入口pathex[],binaries[], datas[("E:/**/templates","/templates"),("E:/**/s…