《Spring实战 第四版》依赖注入&IoC
本文最后更新于 2025年9月12日 下午
书中并没有明确提到IoC这三个字,但是讲述了大量的有关DI的内容。由于我在读这本书前对Spring完全是个小白(只用来做过一些项目,没有系统去了解细节内容),因此我一度以为这本书并没有讲IoC的内容。后来,在网上浏览有关IoC概念的博客后,才发现这两个其实是同一个东西,它们指代的是同一个概念:对象不再需要去自己创建和配置以进行本地初始化,这个任务交给了IoC容器进行控制。这样一来,便可以在Java开发的过程中实现松耦合,减少代码侵入性,甚至可以让对象具有一些其他的特性。接下来将具体讲讲这个DI的理念。
DI (Dependency Injection) 依赖注入
DI的概念实际上与IoC是相同的,可以将这两者视为同一个东西的不同名字。不过也许以后的文章会讲到有关IoC容器的内容,那东西恐怕就不大一样了。
动机
如果一个对象A需要使用另一个对象B的内容或功能,通常来说,对象A总是需要自己管理和创建一个对象B,然后在需要的时候调用对象B的方法。而如果这时,对象B也拥有大量的配置需要进行维护,则对象B的变动总是会对对象A产生较大的影响。这便是高耦合带来的问题。
考虑以下情况:
1 | |
在这个例子中,这个RandomAgent在构造函数中创建了一个RandomStrategy。因此,现在这个代理在定义上来说便只可能去执行这一种策略,如果想要执行另一种策略,要么就新建一个Agent类,要么就改变原有代码结构,这显然不合理。
如果需要让一个代理能够基于给定的配置来执行特定的策略,则需要改变一下代码:
1 | |
这样一来,GeneralAgent便无需自行创建任何策略,而是在构造的时候把策略作为参数传入。
1 | |
这个方法实际上我们在平时的Java开发中也会用到很多,也是十分好理解的一个方式。这个实际上在我看来就是一个典型的策略模式:
- 避免了对象中对外部对象引用的硬编码问题,转而使用可配置对象进行依赖注入。
- 一个组件不再需要知道如何去创建另一个组件。
- 同一个组件可以被不同的组件使用。
当然了,注入一个strategy的方法也不仅仅是在构造函数中进行注入,也可以用setStrategy()来进行注入,不过这不是重点。
事实上,了解并使用过各种设计模式的程序员往往会采取一个最优的方法以达成相同的目的。而这个策略模式,显而易见,也是其中之一。
其实到这里,我们已经找到了一个很好的降耦合的解决方案,甚至可以将以上所有被认为成依赖注入和控制反转的基本原理和动机:
- 对象自己创建组件 外部对象创建组件并将其分配给这个对象
- 对象自己管理组件 外部对象管理组件
- 对象自己销毁组件 外部对象销毁组件
但是,我们又可以注意到如下内容:
- 每次在创建这类对象的时候,程序员都需要再外部手动地将依赖对象传进构造体。如果嵌套创建的对象较多,这一流程也会显得十分繁杂。
细细想来,是否有更好,更无脑的方式来完成这种任务?
Spring的开发者想了一个我认为很多人都会想到,但是觉得麻烦便不会去做的事情:让程序员添加程序的功能,而程序的需求则让程序自己完成。 简单来说,就是让程序自动对这类内容进行分配。这也是我们后面会讲到的自动装配。