使用 Spring.NET 进行依赖注入






4.39/5 (22投票s)
依赖注入及其在 Spring.NET 中的支持方式。
引言
Spring.NET 是从 Java 平台移植过来的流行开源框架之一。它提供了大量的功能,在本文中,我将讨论依赖注入及其在 Spring.NET 中的支持方式。
依赖注入
依赖注入是一种在设计/编译时将使用者与实际实现解耦,并在运行时将它们绑定的技术。
在较低的实现层面,典型的应用程序中会有一个类实现某个逻辑,然后被另一个类使用。之所以需要两个类,会让我们深入讨论代码的模块化、可重用性、可维护性等话题。
当我们在编译时从一个类实例(假设是 ClassA
)中使用另一个类实例(假设是 ClassB
)时,那么对 ClassB
的任何更改都会影响 ClassA
。每次更改,我们都需要重新编译、重新部署整个系统,以及其他相关问题。在这种情况下,ClassA
和 ClassB
之间存在静态或编译时的绑定。
依赖注入是减轻静态绑定痛苦并解耦 ClassA
和 ClassB
的技术之一。最终结果是实现一个解耦或松耦合的系统。
有大量资料可以详细了解 DI。Martin Fowler 有一篇优秀的文章,通过示例解释了相关概念。
使用 Spring.NET 进行 DI
Spring.NET 将 DI 作为开箱即用的解决方案提供。在本文中,我将深入探讨并解释如何利用 Spring.NET 提供的优势。
场景
我创建了一个具有典型的三层结构的应用程序 - 表示层、业务逻辑层 (BLL)、数据访问层 (DAL)。UI 层实现了 MVP 模式,其中我创建了视图 (WinForms)、Presenter 类以及 DataTable
作为模型。
UI 调用 Presenter,Presenter 与 BLL 交互;BLL 与 DAL 交互并从 Northwind 数据库检索数据。
下图展示了应用程序的层次结构
紧耦合系统的局限性
在紧耦合系统中,UI 依赖于 BLL,BLL 依赖于 DAL。如果我们更改 DAL 中的任何内容,所有层都需要重新编译和重新部署。
松耦合系统的优点
相反,如果我们以松耦合的方式开发,就可以避免编译时依赖。实例可以在运行时进行链接。这带来了以下优点:
- 解耦各层
- 能够在运行时链接各层
- 能够在运行时链接不同的实现以用于 QA/测试目的
- 能够独立开发各层,并在后期集成
使用 Spring.NET 实现 DI 的步骤
在讨论了优点之后,现在是时候看看我们如何实现这项技术了。以下是使用 Spring.NET 实现 DI 所需遵循的广泛步骤:
步骤 1
定义各层将公开的接口。
第二步
为你的层定义的接口提供具体的实现。
步骤 3
在 Spring.NET 配置中配置对象。
步骤 4
在运行时使用 Spring.NET API 初始化 Spring.NET 配置。
步骤 5
使用 Spring 工厂为您创建实例。
步骤 6
在调用层中使用 Spring 工厂创建的实例。
实际实现
在对宏观步骤有了了解之后,现在是时候看看具体实现细节了。
我创建了一个包含三个项目的分层应用程序。每个层定义了接口和实现。
定义接口
数据访问层定义了 BLL 将引用的接口。此接口定义了从表中检索数据的方法。
public interface IDAL
{
DataTable GetAll();
DataTable GetById(string ID);
}
提供具体实现
下面展示了 GetAll()
和 GetById()
方法:
public class CustomerDAL : IDAL
{
// Implementation for GetAll()
public DataTable GetAll()
{
// Create connection
// Create command
// Retrieve all records and return as DataTable
}
// Implementation for GetById()
public DataTable GetById(string ID)
{
// Create connection
// Create command with filter criteria
// Retrieve matched records and return as DataTable
}
}
Spring 对象配置
到目前为止一切顺利。现在,是时候理解 Spring 配置了。首先,声明 Spring 配置节,然后定义具有类型和程序集信息的对象/对象节点。对象节点的 name
属性必须是唯一的,它唯一标识该对象。type
指定对象的完整类型。singleton
属性指定是创建一个实例并服务于多个请求(单例实现),还是每次都创建一个新实例。
以下快照展示了应用程序的配置
初始化 Spring 配置
添加对 Spring.Core 程序集的引用。包含对 Spring.Context
和 Spring.Context.Support
命名空间的引用。
使用 ContextRegistry.GetContext()
方法初始化配置。这将验证配置,检查对象是否存在,并返回一个 IApplicationContext
实例。
使用 Spring 获取实例
使用 ContextRegistry.GetContext()
方法返回的 IApplicationContext
实例来获取实例。
// Include namespaces
using Spring.Context;
using Spring.Context.Support;
// Get the context
IApplicationContext applicationContext = ContextRegistry.GetContext();
// Get the instance through Spring configuration
IBLL _customerBLL = applicationContext[“customerBLL”];
// Work with the instance
_customerBLL.GetAll();
使用实例
对象实例化后,您可以继续执行所需的操作。在我们的例子中,Customer DAL 的 GetAll()
方法是从 Customer BLL 实例调用的。
实际应用
在了解了 Spring.NET DI 后,一个显而易见的问题是它如何在实际场景中发挥作用。以下是一些 DI 可以用于实际的案例:
- 可以根据环境在运行时更改依赖层。例如:可以为测试/QA 环境提供测试实现,为生产环境提供实际实现。
- 可以离线进行增量 bug 修复,并在集成/测试阶段进行链接。
- 不同团队并行开发各层,并在集成阶段进行链接。
关于示例应用程序
示例应用程序有两个窗体 - 客户和员工。两者都检索所有数据或基于 ID 的数据。它们遵循相似的模式。
当窗体加载时,使用 Spring.NET 的 DI 技术将 Presenter 初始化为相应的 Presenter。客户窗体与 CustomerPresenter
链接;同样,员工窗体与 EmployeePresenter
实例链接。Presenter 与相应的 BLL 层链接。BLL 层与相应的 DAL 实例链接。
所有这些都通过 Spring.NET 的 DI 技术实现。
结论
依赖注入是帮助构建松耦合系统的关键技术。Spring.NET 将其作为开箱即用的解决方案提供,并且它是 Spring.NET 中其他组件的基础原则。
阅读愉快!编码愉快!