春天不寒----谈spring的依赖注入
当我第一次看到spring的时候就觉得似曾相识。这分明就是反射+配置文件+工厂模式。这样的框架是按照一些准则把设计模式打包成高层的模式。而spring技术中最闪耀的名词绝对少不了控制反转(IoC),依赖注入(D Injection)和依赖倒置(D Inversion)。
不管这些是方法论,还是模式,还是原则,有了这三样东西程序员的春天确实来了。不必再为了每一次的变化而心寒和纠结了。那么这又“反转”又“注入”又“依赖”的,到底是些什么东西呢?他们在干什么呢?不用行么?那么麻烦值得么?再有spring真的这么特别么,别的世界就没有spring么?
首先澄清下概念:“控制反转”,比方说本来你对某样事物有主动控制权,但是你却交了出去,那么你从主动控制转为被动,此即控制反转;“依赖注入”,一个实体依赖另一个实体,但在早期不体现这种依赖关系,而是把这种依赖关系提取出来,在后期注入回去;“依赖倒置”,以前高层依赖底层,但是底层变化后高层就没用了,后来不让高层依赖底层,让它依赖接口,这就是依赖的倒置,面向接口编程就是依赖倒置的灵魂。
以上是我用自己的话对几个概念的解释。不懂没关系,往下看。
先讲个实际生活的例子,假如某一天,您和您一哥们出去吃饭。坐到餐馆以后,您哥们说,“吃什么啊?”;你懒洋洋的说“随便”。
好,故事先就此打住。您这一随便不要紧啊,把吃什么的控制权交了出去啊,于是您和具体食物的关系算是没有了,因为您哥们说得算了。这就是控制反转,本来您可以决定吃米饭还是馒头,但是现在你只知道等下有东西吃但是吃什么你不知道了,因为控制具体吃什么的是您哥们。不过有一条,他一定会给你点能吃的,不能搞来一把锤子,虽然你把控制权交了出去,但是你还是有最基本的要求,能吃,此为一个接口。而后来不管上什么都要实现这个能吃的接口,此为依赖倒置或者说面向接口编程。
接下来,您哥们仔细想了半天,在点菜单上画了这个涂了那个,可他就是不说点了什么,最后给服务员去做了。等了若干分钟,上来两碗米饭,一个小鸡炖蘑菇,一个酸辣土豆丝。
到了此时您才看到他点了什么菜叫了什么饭,这就是依赖注入了。本来您和米饭和小鸡炖蘑菇是有依赖关系的,因为你要吃它们,但是在开始的时候却把你们隔离开,到了吃的时候你才看到它们。
下面我把伪类图画出来
简单的写下代码:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
下面是beans-config.xml的主要内容
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
上面的代码基本演示了这个小故事和依赖注入等相关概念,但这并不是spring的标准开发,虽然这么做无可厚非,利用接口提供服务,并动态调用,这也是依赖注入的一种方式。However,spring只支持设值注入和构造注入,设值注入比较常用,如下更改就是spring的标准设值注入。
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
而新的配置文件如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
这样改变以后,实现Eatable接口的类就会被spring的IoC容器动态注入到类You中,而类You也可以被包装成实现了某个接口的javabean,在更上层应用中使用那个接口来进行操作,而加载过程如出一辙。
在spring世界里,整个流程被框架化了,用配置文件把使用者和javabean或者bean与bean之间解耦。不管什么技术什么模式,要想解耦,一定会抽象出更多的中间层以增加间接性,直接的叫高内聚但是不灵活。为了灵活自己没事找事增加间接性。这就是spring干的事情。也是很多设计模式干的事。
那么回过头再说说,spring所体现出来的解耦,依赖注入是它的专利么?
这问题回答起来太干脆了:不是。在.NET世界,我们习惯使用反射来动态加载类,而在load时使用读配置文件的办法。这样高层的代码编译发布以后不用再变化,只需要改需要加载的装配件和配置文件就好了。
依赖注入就是把原先在一起但没必要在一起的两样东西分开,但是他们毕竟还是有关系的,所以我们就用胶水把他们再粘到一起。整个就是没事找事。
by 千冰念 @ YITIAN Studio
程序员的路是一行一行走出来的,不管多困难,我能做的只是,绝不低头。