Spring中用文言文故事理解IOC以及DI

2023-10-15 13:30

本文主要是介绍Spring中用文言文故事理解IOC以及DI,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

其貌如水而魂似酒,闻而知其性,饮而呛其喉,久而觉其醇。

Spring这东西,第一次听,觉得好像是那么一回事儿;第二次听,觉得好像又不是那么一会回事;听多了,觉得更加面目全非甚至越来越抽象了;直到以后用的多了,来来回回的套路都拆清了,却愈发的觉得其与最开始被叨叨叨描述的庞大与威严景貌相去甚远,才开始逐渐意识到,也许先前的无法解读,可能就是因过度解读所产生的罪孽。




这仿佛是一个变形版的“恐怖谷效应”,也就是说:

  • 一个物,你对他不做任何解读,那它就是一个物,没有争议;
  • 一个物,你对它稍作解读,你开始觉得平凡之物却有神来之笔,寻常之语恰有磅礴之势,物的价值被升华,但这种升华也会造成对其原有形态的撕裂,但因其程度甚微,物还是物
  • 一个物,你对它过度解读,试图把一个物推向一个非物的“王座”,却因为物的固有特性使其永远在无限逼近非物的层次却又不得不永恒的退却在非物的层次之外,撕裂了自己原来的形态却无法进阶成新的形态,这种认知的失衡导致了物亦非物的感觉产生。

在这里插入图片描述


因此,回归正题,个人觉得自己以前也是在通过一些标准化,形象化的解释,试图将机器层面的IOC推向生活层面来尝试理解,但这明显是一种困难的事情,或者说是一件不轻松的事情,因为这个入口开在了一个我不了解的地方,从一个我不了解的ioc开始走到一个我了解的地方,那既然我一开始就不了解,那还怎么走?那不如我们反过来,从一个我们了解的地方反向触摸到一个我们不了解的层次,但又不过分神化,这样也许能帮助我们更好的理解。


故事一:
江边垂钓一老叟,久而无鱼,然自岿然不动,抛竿收竿,钩下无鱼,遂配竿挂饵,挂毕复抛,时近晌午,方得一鱼,收竿而归。归毕,家中小儿出,视之曰:“鱼近肥,吾不食。”叟听罢,认道而返,归鱼入江,起竿而垂,久毕,复得一鱼,收笼而归。归毕,家中小儿出,视之曰:“鱼过羸,吾不食”。叟无奈,携鱼返,抛鱼归故,起竿而垂,骄阳歇力,指西而往,叟终得鱼,收竿归宿,岸风已冷,遂快行。家中小儿饥,故不辩鱼之增减,叟得以腌之,烹之,共食之。


故事二:
江边垂钓一老叟,久而无鱼,遂折竿而弃之,怒曰:“天道无鱼而人道有羹,吾独受此殃人之辘辘呼?” 老叟归,问小儿之所好,儿偏认三尺四寸之鱼,叟听罢拍案挥金,白银灿灿,靓若美人,小儿得金出,至酒栈,抛银两一二,点三尺四寸五香之鱼着六叶香芹浇七勺盐八勺醋拉九处花刀十分清熟。少卿,小儿携鱼归,与老叟品,呼民之乐





解析: 首先,故事一和故事二都是吃鱼,但方式却是截然不同的。在故事一中,老人(程序猿)贯穿了钓鱼,得鱼,烹鱼的始终,而这是一种十分辛苦(高耦合)的工作,假如说在做完之后,小儿(客户)的需求变了,那老人就得重新回去钓鱼,如果小儿(客户)要吃清蒸巨王乌贼(MySql),老人就得回去钓巨王乌贼(new 巨王乌贼的对象),如果小儿(客户)改口味要喝紫皮泥鳅汤(sqlserver),那老人就得回去钓紫皮泥鳅(new紫皮泥鳅的对象),且因为工作复杂度太高,如果老人钓来了鱼但不会烹饪把鱼弄糊了,那这个巨大的影响会导致一切前功尽弃,且因为前面准备的工作过于复杂,老人再准备钓鱼的时候肯定也会头皮发麻。

所以有了故事二,老人(程序猿)问小儿(客户)想吃什么,于是给钱(写好接口),小儿拿钱去买吃食,把钱交给了酒店(顺着接口唤醒了spring),于是酒店(spring)拿钱办事,知道了对方想吃什么鱼(对象),做好之后就把鱼交给了对方,至于怎么做鱼那就是厨子(mapper)的事情了,如此一来工作效率大大提高,执行过程也被大幅度降低难度(解耦),从而让小儿(客户)吃上了鱼,无论他的需求有多么善变。



因此,鱼还是那条鱼,鱼(对象)没有消失,但鱼被操作(对象被new)的权利,已经从老叟(程序猿)的手中被反转到了酒店(spring)的手中,这个操作就叫做IOC(控制反转)。


至于DI(依赖注入),就是拿钱吃鱼,人想要获取热量不再饿肚子,就要依赖鱼所提供的蛋白质营养,而在人挨饿(程序运行)的过程中,Spring悄悄的把鱼拿给(注入给)了客户,用户得以饱食,这个过程叫依赖注入。
这里不好理解是以为“注入”这个词是面向于程序角度来提出的,注入吗,联想就是打针注射,药液混合着血液在人体内流淌,这个流淌本身就是程序运行本身,在血液流淌的时候药液被突然注射了进来,在程序运行的时候对象突然被Spring拿了进来,这个时候用注入就比较合适了。

举个例子:下图左右两个状态,程序嘛,是死的,你给它输入个1,让它运行1+1,那结果就会是2,也就是一个【输入】对应一个【输出】,这个状态是垂直分布的,所以左图的结果就是吃不到。
而右边图,一个死程序垂直跑,中途突然被一个叫Spring的硬塞了一条鱼,程序吃饱了,从而改变了自己曾观测到并认为能够抵达的未来,为了描述这种命运被转变的神秘魅力,以及被改变命运者在一霎间的震惊与迷惑,所以使用了“注入”一词。

在这里插入图片描述

那么接下来我们从一个IDEA例子来理解一下第二种方式的“吃鱼”:

  1. 第一步,想要从酒店买鱼,买虽然方便,但酒店是自己盖的,先开启挖地基。地基就是一个最最普通的Maven项目即可。在这里插入图片描述
  2. 包名和类名之类的就不再演示了,建立好之后我们把这个项目作为父项目,因此删除原来项目带有的src目录,然后在pom.xml导入相应的坐标,取得营销执照。
 		<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.2.5.RELEASE</version></dependency>

在这里插入图片描述

  1. 然后在父项目下建立子模块,在原来的项目上右键建立一个module在这里插入图片描述在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  1. 然后建立对应的包结构,在src/main/java/对应包/pojo层建立一个实体类,实体类生成对应的getset方法,只需要一个字段演示就好,这个对象就是鱼的供应商。在这里插入图片描述
  2. 然后在resources文件夹下beans.xml,当然名字无所谓,将配置信息拷贝进去。这里的bean标签内容是自定义的,id就是随便的一个名字,class是对应的实体类位置,property参数用来指定对应的字段或对象,name是对象或实体类中的字段名,value是赋值。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd"><!--使用spring来创建对象--><bean id="hello" class="com.spring.pojo.Hello"><!--property中value引用的是具体的值,ref参数是应用spring容器中创建好的对象--><property name="str" value="spring"/></bean></beans>

6.写一个测试类

 public class MyTest {public static void main(String[] args) {//获取上下文,获取Spring容器ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");//对象并没有被直接new,而是从spring容器中取,getBean()中填写的是在xml中注册的bean名Hello hello = (Hello) context.getBean("hello");System.out.println(hello);}
}

在这里插入图片描述
输出,发现我们没有new任何关于Hello的对象,但依然出现了结果。在这里插入图片描述
所以,虽然我们没有去new对象,但对象并没有消失而是被Spring建立了,而作为创建对象的主角由程序员反转给了Spring,这就是IOC的实现,而依赖注入是IOC实现的方式。

这篇关于Spring中用文言文故事理解IOC以及DI的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/218037

相关文章

springboot自定义注解RateLimiter限流注解技术文档详解

《springboot自定义注解RateLimiter限流注解技术文档详解》文章介绍了限流技术的概念、作用及实现方式,通过SpringAOP拦截方法、缓存存储计数器,结合注解、枚举、异常类等核心组件,... 目录什么是限流系统架构核心组件详解1. 限流注解 (@RateLimiter)2. 限流类型枚举 (

Java Thread中join方法使用举例详解

《JavaThread中join方法使用举例详解》JavaThread中join()方法主要是让调用改方法的thread完成run方法里面的东西后,在执行join()方法后面的代码,这篇文章主要介绍... 目录前言1.join()方法的定义和作用2.join()方法的三个重载版本3.join()方法的工作原

Spring AI使用tool Calling和MCP的示例详解

《SpringAI使用toolCalling和MCP的示例详解》SpringAI1.0.0.M6引入ToolCalling与MCP协议,提升AI与工具交互的扩展性与标准化,支持信息检索、行动执行等... 目录深入探索 Spring AI聊天接口示例Function CallingMCPSTDIOSSE结束语

Java获取当前时间String类型和Date类型方式

《Java获取当前时间String类型和Date类型方式》:本文主要介绍Java获取当前时间String类型和Date类型方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录Java获取当前时间String和Date类型String类型和Date类型输出结果总结Java获取

Spring Boot Actuator应用监控与管理的详细步骤

《SpringBootActuator应用监控与管理的详细步骤》SpringBootActuator是SpringBoot的监控工具,提供健康检查、性能指标、日志管理等核心功能,支持自定义和扩展端... 目录一、 Spring Boot Actuator 概述二、 集成 Spring Boot Actuat

OpenCV在Java中的完整集成指南分享

《OpenCV在Java中的完整集成指南分享》本文详解了在Java中集成OpenCV的方法,涵盖jar包导入、dll配置、JNI路径设置及跨平台兼容性处理,提供了图像处理、特征检测、实时视频分析等应用... 目录1. OpenCV简介与应用领域1.1 OpenCV的诞生与发展1.2 OpenCV的应用领域2

在Java中使用OpenCV实践

《在Java中使用OpenCV实践》用户分享了在Java项目中集成OpenCV4.10.0的实践经验,涵盖库简介、Windows安装、依赖配置及灰度图测试,强调其在图像处理领域的多功能性,并计划后续探... 目录前言一 、OpenCV1.简介2.下载与安装3.目录说明二、在Java项目中使用三 、测试1.测

Spring Bean初始化及@PostConstruc执行顺序示例详解

《SpringBean初始化及@PostConstruc执行顺序示例详解》本文给大家介绍SpringBean初始化及@PostConstruc执行顺序,本文通过实例代码给大家介绍的非常详细,对大家的... 目录1. Bean初始化执行顺序2. 成员变量初始化顺序2.1 普通Java类(非Spring环境)(

Spring Boot 中的默认异常处理机制及执行流程

《SpringBoot中的默认异常处理机制及执行流程》SpringBoot内置BasicErrorController,自动处理异常并生成HTML/JSON响应,支持自定义错误路径、配置及扩展,如... 目录Spring Boot 异常处理机制详解默认错误页面功能自动异常转换机制错误属性配置选项默认错误处理

java如何实现高并发场景下三级缓存的数据一致性

《java如何实现高并发场景下三级缓存的数据一致性》这篇文章主要为大家详细介绍了java如何实现高并发场景下三级缓存的数据一致性,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 下面代码是一个使用Java和Redisson实现的三级缓存服务,主要功能包括:1.缓存结构:本地缓存:使