3. 控制反转(IoC)
现在让我们重点探讨 Spring 用于配置应用程序的“控制反转”(IoC)概念。为阐明这一概念,让我们回到之前测试应用程序的架构:
![]() |
为了从数据库管理系统(DBMS)中获取数据,测试类必须使用一个实现 [IArticlesDao] 接口的对象提供的服务,例如 [ArticlesDaoPlainODBC] 类型的对象。我们已经探讨了实例化此类对象的两种可能方案:
- 在第一种方案中,测试类本身请求实例化一个 [ArticlesDaoPlainODBC] 类型的对象:
<TestFixture()> _
Public Class NunitTestArticlesDaoPlainOdbc
' the test object
Private articlesDao As IArticlesDao
<SetUp()> _
Public Sub init()
' create an instance of the object to be tested
articlesDao = New ArticlesDaoPlainODBC("odbc-firebird-articles", "SYSDBA", "masterkey")
End Sub
...
End Class
代码中存在对类名的硬编码依赖。如果实现 [IArticlesDao] 接口的类发生变更,则 [init] 方法中的代码也需要进行修改。对象之间存在以下关系:
![]() |
[NunitTestArticlesDaoPlainOdbc] 类主动创建其所需的 [ArticlesDaoPlainODBC] 对象。回到“控制反转”这一术语,可以说正是该类“控制”着所需对象的创建。
- 第二个解决方案采用了不同的方法。测试类现在变成了如下形式:
<TestFixture()> _
Public Class NunitSpringTestArticlesDaoPlainOdbc
' the test object
Private articlesDao As IArticlesDao
<SetUp()> _
Public Sub init()
' retrieve an instance of the Spring object manufacturer
Dim factory As XmlObjectFactory = New XmlObjectFactory(New FileStream("spring-config-plainodbc.xml", FileMode.Open))
' request instantiation of the articles dao object
articlesDao = CType(factory.GetObject("articlesdao"), IArticlesDao)
End Sub
...
End Class
该机制可概括如下:
![]() |
在此,测试类并未主动请求创建 [ArticlesDaoPlainODBC] 对象,而是仅向 Spring 请求该对象的引用。若对象已存在,Spring 便返回其引用;若不存在,Spring 则会创建该对象。测试类已无法控制 [ArticlesDaoPlainODBC] 对象的创建过程,它仅需请求该对象的引用。 在此情况下,该请求将迫使 Spring 创建该对象。然而,在另一种情境下,可以设想所请求的对象已应应用程序的要求被创建。此时 Spring 不会重新创建该对象,而是返回对现有对象(单例)的引用。控制反转(IoC)的概念在此处的含义是:
- 应用程序绝不会主动创建所需的单例,它仅请求这些单例的引用。
- 由 Spring 决定在首次请求单例引用时创建该单例


