领先一步
VMware 提供培训和认证,助力您的职业发展。
了解更多对于 Spring.NET 来说,这是非凡的一年。我们在12月正式发布之前经历了两个里程碑版本和两个候选版本。1.1 版本的首批代码早在2004年末就由 Aleks Seovic 完成,他当时开始了 ASP.NET 框架的工作。简而言之,它经历了漫长的开发过程。作为一年的结束,这是一个自然而然回顾过去和现在的时候,我想感谢项目的其他成员和 Spring.NET 社区的所有贡献和支持。我期待着美好的2008年!
Spring.NET 1.1 的功能集相当广泛。包括用于依赖注入的 IoC 容器、AOP、ASP.NET 框架、声明式事务管理和更多功能。然而,提高代码结构和可测试性的最大收益是向你的开发者工具箱中添加依赖注入和 AOP。在这两者中,依赖注入是更基础的技术,我想就配置 Spring.NET 容器的选项提供一些额外信息。
显然,配置容器最常见的方式是通过 XML。XML 虽然提供了很大的灵活性,但它很冗长,而且大家聚在一起喝啤酒时都很乐意吐槽自己有多讨厌 XML 配置文件(无论是 Spring 还是其他)。编写自定义文件可以极大地减少冗长性,移除许多样板 XML,并提供专注于特定领域的属性。例如,Spring.NET 为事务管理和 AOP 配置提供了此功能。然而,在非 XML 配置方面有个好消息,Spring.NET 在下一版本中将添加基于属性的 DI 和程序集中的注解类自动检测。正如您所料,提供的功能将与 Spring Java 中的非常相似(参见此处和此处),但会进行调整,特别注意移除不必要的 Java 构件(如 JSR-250 属性)并引入仅在 .NET 上有意义的新特性(如利用方法参数名称实现按名称注入语义)。
需要记住的一点是,核心容器不依赖于基于 XML 的对象定义。容器有其内部的对象定义模型。因此,对象定义可以来自多种格式。据我目前所读,特别吸引人的是使用 DSL 工具包配置异常处理通知。其他有趣的配置方法是使用脚本语言 DSL(关于 Spring Java + Groovy 集成,请参见此帖子)。最终,目标是让您可以针对手头的任务选择多种配置方法。
在当前版本中,有一些关于容器的程序化控制和配置的功能似乎并不广为人知。这里是对这些功能的简要概述。我很快会在参考文档中提供更完整的描述。
主要的 IoC 容器接口,IApplicationContext,包含方法 ConfigureObject(object objectToConfigure, string objectDefnitionName)
基于与名称关联的对象定义,容器将对传入的实例执行依赖注入。当您需要运行时创建对象以响应用户请求时,这特别有用。在这种情况下,您通常会向构造函数传入一些特定于当前情况的数据,然后让容器配置对象中对所有用户请求都通用的其余依赖项。
此功能在 IApplicationContext
的一个子接口上定义,即IApplicationContext,即IConfigurableApplicationContext。调用代码如下所示
((IConfigurableApplicationContext) applicationContext).ObjectFactory.RegisterSingleton("ObjectB", myObjectBInstance);
注册的对象不会被修改;它只是按原样存储在提供的名称下。但是,其他对象可以引用此注册对象作为依赖项。
按名称检索对象很简单
object o = applicationContext.GetObject("AccountManager")
然后转换为适当的类型。您也可以按类型获取对象
IDictionary dict = context.GetObjectsOfType(typeof (IAccountManager));
这些 API 调用需要一些改进,使其泛型化,并提供一个便捷方法来获取指定类型的单个对象,而不是集合。
类GenericApplicationContext是一个不假设任何特定对象定义格式的 IoC 容器。您可以像这样从嵌入资源中加载基于 XML 的对象定义
GenericApplicationContext ctx = new GenericApplicationContext();
IObjectDefinitionReader objectDefinitionReader = new XmlObjectDefinitionReader(ctx); objectDefinitionReader.LoadObjectDefinitions("assembly://MovieFinder/AppContextContribution.xml");
然后,您可以使用 构建其他对象定义并添加到上下文中ObjectDefinitionBuilder. ObjectDefinitionBuilder提供一个简单的流畅接口来简化对象定义的创建。因此,它ObjectDefinitionBuilder允许您将方法调用链接起来,以创建与您熟悉的 Spring XML 中的元素大致对应的对象定义。
IObjectDefinitionFactory objectDefinitionFactory = new DefaultObjectDefinitionFactory();
ObjectDefinitionBuilder builder = ObjectDefinitionBuilder.RootObjectDefinition(objectDefinitionFactory, typeof(ColonDelimitedMovieFinder));
builder.AddConstructorArg("movies.txt") .SetLazyInit(true);
ctx.RegisterObjectDefinition("AnotherMovieFinder", builder.ObjectDefinition); // 处理对象定义… ctx.Refresh()
这段代码取自更新后的“MovieFinder”示例,您可以从每晚构建中下载。另外提一下,IObjectDefinitionFactory还有另一个替代实现,WebObjectDefinitionFactory,用于 ASP.NET 页面和用户控件,尽管在这种情况下您不太可能使用它。
这里是另一个使用 的附加人工示例TestObject类,展示了更多ObjectDefinitionBuilderAPI。
ObjectDefinitionBuilder builder = ObjectDefinitionBuilder.RootObjectDefinition(objectDefinitionFactory, typeof (TestObject));
builder.AddPropertyValue("Age", 22) .AddPropertyValue("Name", "Joe") .AddPropertyReference("Spouse", "Spouse") .SetSingleton(false);
ctx.RegisterObjectDefinition("TestObject", builder.ObjectDefinition);
builder = ObjectDefinitionBuilder.RootObjectDefinition(objectDefinitionFactory, typeof(TestObject));
IList friends = new ArrayList(); friends.Add(new TestObject("Dan", 34)); friends.Add(new TestObject("Mary", 33));
builder.AddPropertyValue("Friends", friends) .AddConstructorArg("Susan") .AddConstructorArg(23) .SetSingleton(false);
ctx.RegisterObjectDefinition("Spouse", builder.ObjectDefinition);
如果您已经有一个基于 XML 的应用程序上下文,您可以将其传递给 GenericApplicationContext
的构造函数,这意味着它将在简单的根/子层次结构中充当后者的父应用程序上下文。您还可以使用GenericApplicationContext,这意味着它将在简单的根/子层级结构中作用于后者的父级应用上下文。你也可以将该上下文注册到ContextRegistry下,以便提供服务定位器风格的查找。
目前,ObjectDefinitionBuilderObjectDefinitionBuilder
API 相当“字符串化”,这意味着虽然可以注册对象以便“按类型”注入,但这比实际需要更冗长。改进此 API 的“流畅性”是未来版本中另一个需要改进的领域。
好了,就到这里了。祝大家新年快乐!