本文主要是介绍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例子来理解一下第二种方式的“吃鱼”:
- 第一步,想要从酒店买鱼,买虽然方便,但酒店是自己盖的,先开启挖地基。地基就是一个最最普通的Maven项目即可。
- 包名和类名之类的就不再演示了,建立好之后我们把这个项目作为父项目,因此删除原来项目带有的src目录,然后在pom.xml导入相应的坐标,取得营销执照。
<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.2.5.RELEASE</version></dependency>
- 然后在父项目下建立子模块,在原来的项目上右键建立一个module
- 然后建立对应的包结构,在src/main/java/对应包/pojo层建立一个实体类,实体类生成对应的getset方法,只需要一个字段演示就好,这个对象就是鱼的供应商。
- 然后在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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!