领先一步
VMware 提供培训和认证,以加速您的进步。
了解更多对于 Spring.NET 来说,这确实是不平凡的一年。在 12 月份发布 GA 版本之前,我们经历了两个里程碑和两个候选版本。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的子接口上,即IConfigurableApplicationContext。调用代码如下所示
((IConfigurableApplicationContext) applicationContext).ObjectFactory.RegisterSingleton("ObjectB", myObjectBInstance);
注册的对象不会被修改;它只是按原样存储在提供的名称下。但是,其他对象可以将此注册的对象作为依赖项引用。
按名称检索对象很简单
object o = applicationContext.GetObject("AccountManager")
然后转换为相应的类型。您也可以按类型请求对象
IDictionary dict = context.GetObjectsOfType(typeof (IAccountManager));
这些 API 调用需要一些 TLC,方法是使它们泛型以及提供一个方便的方法来获取指定类型的单个对象而不是集合。
类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”示例,您可以从 nightly build 中下载该示例。顺便说一句,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的构造函数,这意味着它将在简单的根/子层次结构中充当后者的父应用程序上下文。您还可以使用名称在ContextRegistry中注册上下文,以提供服务定位器样式的查找。
按原样,ObjectDefinitionBuilderAPI 非常“字符串化”,这意味着虽然可以注册用于“按类型”连接的对象,但它比需要的冗长。改进此 API 的“流畅性”是未来版本改进的另一个领域。
好了,现在就到这里了。祝大家新年快乐!