Spring 控制反转和依赖注入理解

1什么是控制反转

IOC,全称是inversion of control,就是控制反转,不是一种技术,而是一种设计思想。在Java开发中,IOC的意味着,将我们设计好的类对象的控制权交给容器去控制,而不是我们自己用代码去显式的new或者销毁。理解好控制反转的,就首先要明白:在传统法中和IOC中,谁控制谁,控制什么,什么东西反转了。

谁控制谁,控制什么
在传统程序设计中,我们的对象依赖依赖别的对象时,可以自己直接显式的new一个对象实例出来,这个过程中,程序在我们的命令下,主动去new了一个依赖的对象实例出来;而在IOC中,new对象的过程是有IOC容器控制的,即为,在IOC框架下,我们的对象代码中不会出现new Object()这样类似的去显式创建对象的语句,这一过程被IOC容器偷偷做了,然后偷偷的把自己new出来的对象的传给(或者叫“注入”)了我们需要这个对象的地方。
同时,IOC容器对象控制的不仅仅有对象实例的创建,包括不限于文件等外部资源等。

哪些方面进行了反转
有反转就由正转,传统应用程序中,是有我们自己手动new对象就是正转;现在有IOC容器控制即为反转,容器帮我们查找了我们写的类中需要注入的对象(就是我们原本打算new一个出来获得的),然后容器按需求偷偷偷出来并注入到我们的对象中;从上述描述来看,就是依赖对象(就是我们要new的对象,我们可能用这个对象里的方法或者属性,我们依赖这个对象实例)的获取过程反转了。

1.1 举例说明正转和反转

假设有一个的客户端类,客户端类的属性有个用户类的列表,而每个用户类中又包含了用户信息类,因此,有这样的依赖关系:客户端类 依赖 用户类 ,用户类 依赖 用户信息类。现在我们的的目标是向列表中加一个用户,于是就需要根据下图的步骤进行代码实现:
Spring 控制反转和依赖注入理解
可见,我们需要用代码显式创建两个类实例,并将其中一个set为另一个的属性。
那么,在IOC框架下,我们需要写那些代码呢?
Spring 控制反转和依赖注入理解
可见,我们唯一要做的就是告诉容器,我们想要一个用户类,然后就我们的拿到一个用户类实例了,IOC容器会替我们的做完背后的操作。
因此,IOC框架下,对象好像都有了生命一样,它会自己自动(其实是IOC容器做的……)去new一个自己需要的对象实例出来并set给自己

1.2 IOC能做什么

IOC不是一种技术,而是一种思想,跟依赖倒置有点类似,这是一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统额应用程序都是我们在类的内部主动创建依赖对象,从容导致类与类之间高耦合,难以进行单元测试(由此出现了mock);有了IOC容器后,我们把查找依赖和创建依赖的控制权交给了容器,由容器进行注入、组合对象,所以,对象与对象之间是松散耦合的,方便了测试了,也方便了重复利用,也使得架构变的灵活。
IOC对编程带来的最大变化是,在思想上,发生了“主从变化”。传统下,我们的自己写出来的程序中,包含了很多new等等操作,要什么资源都是主动获取的;但是,在IOC下,应用程序变成了被动,等着被IOC容器把new好的资源塞给自己。
IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。

2 依赖注入

Dependency Injection,DI,即为依赖注入,就是IOC容器会按照对象的需要将依赖注入到对象中,这个过程在运行期才会出现。依赖注入是实现控制反转的某一环节,但是!依赖注入并不是只能用于控制反转。在dropwizard中,@service和@inject就是比较明显的依赖注入的例子!
通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。
理解依赖注入的关键是清楚:

  • 谁依赖于谁:个人认为,最直接的依赖还是那个依赖的对象,只不过这个被依赖的对象是由IOC容器创建的,因此,可进一步说,依赖的是IOC容器;
  • 为什么需要依赖:IOC框架下,IOC容器掌握了资源的控制权,应用程序和对象的依赖,本质就是内存资源;
  • 谁注入谁:IOC容器向对象/应用程序中注入资源;
  • 注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)