Spring核心和设计思想(1)

1.Spring是什么?

我们通常说的Spring指的是Spring FrameWork(Spring 框架),它是一个开源框架,有着活跃而庞大的社区,这就是它长久不衰的原因。Spring支持广泛的应用场景,它让Java企业级的应用程序开发起来更简单。在18年以前,开发大多使用的Spring框架,学会Spring框架我们就能维护公司以前写的代码。

Spring:包含了众多工具方法的IoC容器。

那么什么是容器?什么是IoC?什么是IoC容器?

1.1什么是容器?

按照我们的理解,容器是容纳某种物品的装置。

我们熟悉的有LinkedList,ArrayList等都可以被称为容器,容纳某种类型数据。

1.2什么是IoC?

IoC的全名是Inversion of Control翻译成中文“控制反转”的意思。那这句话到底什么意思呢?控制什么?反转什么呢?

1.2.1传统程序开发

假如,我们现在要构建一辆“车”的程序,我们的实现思路可能是这样的

 构建一辆车(Car Class),我们需要依赖车身(FrameWork Class),而车身需要依赖地盘(Bottom Class),而地盘需要依赖轮胎(Tire Class),最终程序的代码实现如下:

/**
 * Describe:
 * User:lenovo
 * Date:2023-07-18
 * Time:10:39
 */
public class NewCarExample {
    public static void main(String[] args) {
        Car car = new Car();
        car.init();
    }

    /**
     * 汽车对象
     */
    static class Car {
        public void init() {
            //依赖车身
            Framework framework = new Framework();
            framework.init();
        }
    }

    /**
     * 车身类
     */
    static class Framework {
        public void init() {
            //依赖底盘
            Bottom bottom = new Bottom();
            bottom.init();
        }
    }

    /**
     * 地盘类
     */
    static class Bottom {
        public void init() {
            //依赖轮胎
            Tire tire = new Tire();
            tire.init();
        }
    }

    /**
     * 轮胎类
     */
    static class Tire {
        private int size = 30;
        public void init() {
            System.out.println("轮胎尺寸" + size);
        }
    }
}

传统的开发缺陷

在以上的程序中,轮胎的尺寸是固定的,但是随着对车需求的增大,个性化的需求也变得越来越多,这个时候我们就需要加工多种多样的轮胎,我们就对代码进行修改,如下所示:

/**
 * Describe:
 * User:lenovo
 * Date:2023-07-18
 * Time:10:39
 */
public class NewCarExample {
    public static void main(String[] args) {
        Car car = new Car(20);
        car.init();
    }

    /**
     * 汽车对象
     */
    static class Car {
        private Framework framework;
        
        public Car(int size) {
            framework = new Framework(size);
        }
        public void init() {
            //依赖车身
            framework.init();
        }
    }

    /**
     * 车身类
     */
    static class Framework {
        private Bottom bottom;
        
        public Framework(int size) {
            bottom = new Bottom(size);
        }
        //依赖底盘
        public void init() {
            bottom.init();
        }
    }

    /**
     * 地盘类
     */
    static class Bottom {
        private Tire tire;
        
        public Bottom(int size) {
            tire = new Tire(size);
        }
        
        public void init() {
            //依赖轮胎
            tire.init();
        }
    }

    /**
     * 轮胎类
     */
    static class Tire {
        private int size;
        
        public Tire(int size) {
            this.size = size;
        }
        
        public void init() {
            System.out.println("轮胎尺寸" + size);
        }
    }
}

以上程序的问题:当最下层的代码改动以后,整个调用链上的所有代码都发生了改动。

如何解决上述问题呢?

我们可以尝试不在每个类中创建自己的下级类,如果自己创建下级类就会出现这样的连锁反应。此时我们需要将自己创建的下级类,改为传递的方式(也就是注入的方式),因为我们不需要在当前类中创建下级类,所以下级类即使发生了变化(创建或减少参数),当前类也不用修改,这样就完成了程序的解耦了

PS:解耦指的是解决了代码的耦合性,耦合性也就可以换一种叫法叫程序的相关性。好的程序代码的耦合性(代码之间的相关性)是很低的。

1.2.2控制反转式程序开发

基于上面的思路,我们把调用汽车的陈旭示例改造以下,把创建子类的方式,改为注入传递的方式,具体实现代码如下:

public class NewCarExample3 {
    public static void main(String[] args) {
        Tire tire = new Tire(20);
        Bottom bottom = new Bottom(tire);
        Framework framework = new Framework(bottom);
        Car car = new Car(framework);
        car.init();
    }

    /**
     * 汽车对象
     */
    static class Car {
        private Framework framework;

        public Car(Framework framework) {
            this.framework = framework;
        }
        public void init() {
            //依赖车身
            framework.init();
        }
    }

    /**
     * 车身类
     */
    static class Framework {
        private Bottom bottom;

        public Framework(Bottom bottom) {
            this.bottom = bottom;
        }
        public void init() {
            bottom.init();
        }
    }

    /**
     * 地盘类
     */
    static class Bottom {
        private Tire tire;

        public Bottom(Tire tire) {
            this.tire = tire;
        }
        public void init() {
            tire.init();
        }
    }

    /**
     * 轮胎类
     */
    static class Tire {
        private int size;

        public Tire(int size) {
            this.size = size;
        }
        public void init() {
            System.out.println("轮胎尺寸" + size);
        }
    }
}

代码经过上面的调整,不论底层类如何变化,整个调用链式不用做任何更改的,这样就完成了代码之间的解耦

1.2.3对比总结规律

在传统的代码种对象创建的顺序是:Car -> Framework -> Bottom -> Tire,改进之后解耦的代码的对象创建顺序是:Tire -> Bottom -> Framework -> Car.

通用代码的实现代码,类的创建是反的,传统代码种是Car控制并创建了Framework,Framework创建并创建了Bottom,依次往下,而改进后控制权发送了反转,不再是上级对象创建并控制下级对象了,而是下级对象把注入当前对象中,下级的控制权不再由上级类控制了,这样即使下级类发生了改变,当前类都是不会收到影响的,这就是经典的控制反转,也就是IoC的实现思想。

1.3理解Spring IoC 

回到刚刚说的那句话来,Spring是包含了多个工具方法的IoC容器。那它就具备两个基本的功能:

  • 将对象存放到容器中
  • 从容器中取出对象

也就是说学Spring最核心的功能,就是学如何将对象存入到Spring中,再从Spring中获取对象的过程。

将对象存放到容器中的好处:将对象储存在IoC容器相当于将以后可能会使用到的所用工具依次性制作好都放到仓库中,需要的时候直接取出来,用完再把它放回到仓库。而new对象的方式相当于,每次需要工具了,才现做,用完了就扔掉了,也不会保存,下次再使用的时候就需要重新做了,这就是IoC容器和普通程序开发的区别。

Spring是一个IoC容器,说的是对象的创建和销毁的权利都交接给Spring来管理了,它本身又具备了存储对象和获取对象的能力。

1.4DI概念说明

说到Ioc不得不提及一个词“DI”,DI的全称是Dependency Injection的缩写,翻译成中文是“依赖注入“的意思

依赖注入,就是由IoC容器在运行期间,如果需要一个对象,无须new创建,而是依赖外部的注入。

就如上面代码的例子,我们造一辆车需要车架,我们不要自己创建车架,而是传入一个车架类型的参数(相当于直接去拿一个现成的车架),这就是依赖注入

依赖注入(DI)和控制反转(IoC)是从不同地角度描述的同一件事情,就是指通过引入IoC容器,利用依赖关系注入的方式,实现对象之间的解耦。换句话来说,实现控制反转的实现方式之一是依赖注入

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

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

相关文章

用html+javascript打造公文一键排版系统5:二级标题排版

公文中二级标题的一般以(X)标注(其中X为由"一二三四五六七八九十"中的字符组成的字符串),用楷体字加粗。 首先我们要判断一段文字是否包含二级标题,最简单的方法 就是判断文字中的头一个字符是否…

【Linux】Linux下的项目自动化构建工具——make和makefile

❤️前言 大家好,好久不见!今天小狮子为大家带来的文章是一篇关于Linux下的项目自动化构建工具——make和makefile的博客,希望能帮助到大家。 正文 当我们进行涉及多文件的工程开发时,我们需要对很多不同类型、不同功能&#xff…

基于R语言Meta分析与【文献计量分析、贝叶斯、机器学习等】多技术融合方法与应用

Meta分析是针对某一科研问题,根据明确的搜索策略、选择筛选文献标准、采用严格的评价方法,对来源不同的研究成果进行收集、合并及定量统计分析的方法,最早出现于“循证医学”,现已广泛应用于农林生态,资源环境等方面。…

XUbuntu22.04之解决蓝牙鼠标不停掉线问题(追凶过程)(一百八十五)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…

Linux网络基础 — 网络层

目录 IP协议 IP协议报头格式 网段划分 特殊的IP地址 IP地址的数量限制 私有IP地址和公网IP地址 路由 补充 网络层 在复杂的环境中确定一个合适的路径。 IP协议 ip具有将数据从 主机A 跨网络送到 主机B 的能力。 主机: 配有IP地址,但是不进行路由控制的设备…

【Redis】Transaction(事务)

🎯前言 Redis事务是一个组有多个Redis命令的集合,这些命令可以作为一个原子操作来执行。 Redis事务通常用于以下两种情况: 保证操作的原子性:在多个命令的执行过程中,如果有一个命令执行失败,整个事务都需…

挖矿记录+解决方案:利用GitLab组件对服务器进行挖矿导致CPU占用200%

文章目录 什么是云服务器挖矿?事件记录事件分析产生影响解决方案后期预防什么是云服务器挖矿? 云服务器挖矿是指利用云服务器从事赚取比特币的活动。比特币是一种虚拟数字货币,挖矿是将一段时间内比特币系统中发生的交易进行确认,并记录在区块链上形成新区块的过程。 用于…

【字节流】写数据的三种方式以及两个问题

字节流写数据 1.字节流写数据三种方式 void write(int b):将指定的字节写入此文件输出流一次写一个字节数据 package com.bytestream; import java.io.FileOutputStream; import java.io.IOException; public class FileOutputStreamDemo02 {public static void ma…

融云「北极星」数据监控平台:数据可视通晓全局,精准分析定位问题

↑ 点击预约“融云北极星”直播↑ 点击预约“实时社区”直播 近期,融云“北极星”数据系统完成功能迭代,新模块“数据监控平台”正式“履新上任”。关注【融云全球互联网通信云】了解更多 点击图片查看更多详情 此前,“北极星”系统主要为客…

水声功率放大器的作用是什么

水声功率放大器是一种专门用于水声设备的高功率电子设备,主要用于提升水下信号的传输距离和保证语音清晰度。它的作用在水下通信、水下测量、海洋科学等领域都非常重要。 其主要作用有以下几个方面: 增强信号传输距离 水声信号在水中传播会受到各种因素的…

有哪些好用的远程传输大文件的软件

随着网络技术的日益进步和普及,大文件远程传输已经成为了人们生活和工作中必不可少的一部分。然而,在远程传输大文件的过程中,经常会遇到传输速度慢、容易受到干扰等问题,因此需要一款高效、稳定、安全的大文件远程传输软件来解决…

离线安装docker

目录 1、下载docker 安装包 2、上传docker 到服务器目录/opt/ 3、解压docker-19.03.9.tgz 4、解压的docker文件夹全部移动至/usr/bin目录 5、将docker注册为系统服务 6、重启生效 6.1、重新加载配置文件 6.2、启动Docker服务 6.3、查看启动状态 ​6.4、 设置docker为开…

伦敦金分析时切勿过分自信

伦敦金价格会呈趋势变动,这是投资者进行技术分析最根本、最核心的因素。根据物理学上的动力法则,趋势的运行会延续,直到有反转的现象产生为止。事实上,虽然伦敦金的价格不断上下波动,但终究是朝一定的方向前进的&#…

数组

数组: 数字组成的组,组里即可以,int类型,string,字符串,数组当中的数据类型,可以由用户自定义 同一种,也可以是不同的数据类型组成的元素集合 数组最大的作用,可以一次…

JVM系列(5)——类加载过程

一、类的生命周期 加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using&#xff09…

在ICC/ICC2/FC中运行Calibre

1. which calibre找到calibre的安装目录 > which calibre > /eda/mentor/ixl_cal_version/bin/calibre 2. 在 /eda/mentor/ixl_cal_version目录下使用find ./* -name "icc_calibre.tcl",找到icc_calibre.tcl 3. 打开icc_calibre.tcl里面有不同工具(ICC2/FC/…

uniapp 封装公共方法(无需每个页面引用,直接调用)

封装方法: 1. 在根目录下建立common文件夹 创建com.js 2.在main.js中挂载(写在定义vue之后) import $com from /common/com.js Vue.prototype.$com $com 3.在com.js中按照以下格式定义方法 export default {//定义需要的方法 } 4.使用 click"$com.已经定义的方法名&q…

Java 装箱拆箱原理 包装类型缓存池

JAVA中的基本数据类型 byteshortintlongfloatdoublebooleanchar 为了让上述基本数据类型可以转为对象,Java在1.5推出了一系列包装类,基本类和包装类互相转换的过程,称为装箱和拆箱 缓存池 缓存池也叫常量池。它是事先存储一些常量数据用以…

openvpnas安装,可视化远程连接控制

本次安装环境为 centos7.9 本次安装软件为 openvpnas, 默认是两个连接授权,可以通过代码注入实现多连接授权 1.基础环境以及Python36安装 yum install python36 python36-devel wget -y 2.安装 openvpnas 1.在线安装 yum -y install https://as-repository.openv…