IObjectFactory和IApplicationContext
Spring.Core程序集是Spring.NET控制反转(IoC,也叫做依赖注入)功能的基础。Spring.Core程序集中的IObjectFactory接口为Spring.NET提供了一种高级的配置机制,可用所有可能的存储介质保存任意对象的配置信息。同位于此程序内的IApplicationContext接口则扩展了IObjectFactory,增加了面向方面编程(AOP)和消息资源处理(用于国际化)等功能。简单的说,IObjectFactory接口提供了配置框架和基本功能,IApplicationContext接口又在其基础上扩展了许多企业级特性。可以说IApplicationContext是IObjectFactory的一个超集,具备IObjectFactory所有的功能与行为。
IObjectFactory和IApplicationContext
IObjectFactory是初始化、配置及管理对象的实际容器(它是所有容器的父接口)。对象间通常会相互协作,我们也可以说它们相互间具有依赖性。这些依赖性通过IObjectFactory的配置数据反映出来。(但某些依赖性从配置数据中是看不到的,比如运行时对象之间的方法调用。)Spring.Objects.Factory.IObjectFactory接口有多个实现类。最常用的是Spring.Objects.Factory.Xml.XmlObjectFactory。
Spring.NET框架的核心原则是非侵入性。简单的说,就是应用程序的代码不需要对Spring.NET的API有任何依赖。然而,如果要通过IObjectFactory或Spring.Context.IApplicationContext接口充分利用IoC容器的功能,有时候还必须要初始化这两个接口的某个实现类。为此,可以在代码中使用new操作符来显式创建容器(后文中,凡涉及到含义为“管理对象的容器”而非特指接口的名称时,将原文中的IObjectFactory或IApplicationContext称为“容器”或“IoC容器”);另一种更为简单的方式是在.NET应用程序的标准配置文件中用一个自定义节点来配置容器。一旦容器建立,应用程序代码就可能不再需要与之发生显式的交互了。
下面代码创建了XmlObjectFactory类的一个实例,XmlObjectFactory是IObjectFactory的实现类之一。我们假定在objects.xml文件中定义了要装配和发布的服务对象。将该文件的信息传递给XmlObjectFactory的构造器,即可创建一个容器,参见如下代码:
- IResource input = new FileSystemResource ("objects.xml");
- IObjectFactory factory = new XmlObjectFactory(input);
代码中使用了Spring.NET的IResource接口。IResource能以简单统一的方式访问许多可用System.IO.Stream表示的IO资源。这些IO资源一般是独立的文件或者URL,但也可以是.NET程序集的内嵌资源。通过IResource接口,可以用简单的URI格式来描述资源的位置。此外,IResource也支持很多其它协议,如http等。
前文提到IApplicationContext是IObjectFactory的超集,我们一般都会用IApplicationContext来作为容器。在创建容器时可以像上例一样用IResource实例化IApplicationContext接口的任何一个实现类。另外,IApplicationContext支持用多个配置文件创建容器(此处的配置文件是指包括了Spring.NET对象定义的XML文件,而非特指.config文件,下同):
- IApplicationContext context = new XmlApplicationContext(
- "file://objects.xml",
- “assembly://MyAssembly/MyProject/objects-dal-layer.xml");
- // of course, an IApplicationContext is also an IObjectFactory...
- IObjectFactory factory = (IObjectFactory) context;
下面是引用.NET程序集内嵌资源时的URI语法:assembly://<AssemblyName>/<NameSpace>/<ResourceName>
注意 | |
---|---|
若要在VS中创建一个内嵌的资源,必须在文件属性编辑器中将xml文件的Build Action设为Embedded Resource。并且,如果自上次成功建立项目之后,该属性的变更是本次所做的唯一更改,则需要显式的重新生成项目。如果使用NAnt建立项目,需要在csc任务中添加一个<resources>节点。可参见Spring.Core.Tests项目中的build文件,该项目随Spring.NET一起发布。 |
更好的创建方式是在标准.NET应用程序配置文件中(App.config或Web.config)添加自定义配置节点。以下的XML节点可以创建与前例相同的容器:
- <spring>
- <context type="Spring.Context.Support.XmlApplicationContext, Spring.Core">
- <resource uri="file://objects.xml"/>
- <resource uri="assembly://MyAssembly/MyProject/objects-dal-layer.xml"/>
- </context>
- </spring>
<context>节点的type属性是可选的,在Windows应用中,其默认值就是Spring.Context.Support.XmlApplicationContext,所以下面的配置和上面完全相同:
- <spring>
- <context>
- <resource uri="file://objects.xml"/>
- <resource uri="assembly://MyAssembly/MyProject/objects-dal-layer.xml"/>
- </context>
- </spring>
spring和context节点的名称不是任意的,必须是"spring"和"context",Spring.NET本身将"spring/context"作为字符串常量定义在了AbstractApplicationContext类中以表示上下文的节点名称。若要引用由以上配置创建的容器,可使用下面的代码:
- IApplicationContext ctx = ContextRegistry.GetContext();
ContextRegistry类既可用来初始化应用程序上下文,也可用来以服务定位器风格对容器中的对象进行访问。注意,使这一切成为可能的是Spring.Context.Support.ContextHandler类,该类实现了FCL的IConfigurationSectionHandler接口。必须在.NET配置文件的<configSections>节点中注册这个类,如下所示:
- <configSections>
- <sectionGroup name="spring">
- <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
- </sectionGroup>
- </configSections>
注册了这个节点处理器后,配置文件中的<spring>节点才能起作用。
在某些情况下,用户不需要以任何方式显式创建容器,Spring.NET可以自行创建。例如,Spring.NET中的Spring.Web模块可以将IApplicationContext作为Web应用程序正常启动进程的一部分进行自动装载。目前正在研究如何为WinForms应用程序提供类似的支持。
下面我们先讨论IObjectFactory接口所使用的对象配置格式。(凡适用于IObjectFactory的内容,必定也适用于IApplicationContext)
基本上,IObjectFactory的配置信息由一个或多个对象定义构成。在基于XML的工厂中,这些对象定义表现为一个或多个<object>子节点,它们的父节点必须是<objects>(objects节点的xmlns元素是必需的,必须根据不同的应用添加不同的命名空间,请留意各个章节中的相关内容。
- <objects xmlns="http://www.springframework.net"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.net
- http://www.springframework.net/xsd/spring-objects.xsd">
- <object id="..." type="...">
- ...
- </object>
- <object id="...." type="...">
- ...
- </object>
- ...
- </objects>
随Spring.NET一起发布的schema文档可以简化对XML对象定义的验证过程。目前,除了验证XML文档外,该文档还有一个用途,就是在具备XSD感知能力的编辑器(比如VS.NET)内进行代码提示。在Spring.NET的网站上可以下载到spring-objects.xsd的最新版本。
XML对象定义也可以放在.NET的标准应用程序配置文件中。此时也需要为<objects>节点预先注册相应的节点处理器,类型为Spring.Context.Support.DefaultSectionHandler。然后,就可以在.NET的.config文件中为一或多个容器配置对象定义了,如下所示:
- <configuration>
- <configSections>
- <sectionGroup name="spring">
- <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
- <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
- </sectionGroup>
- </configSections>
- <spring>
- <context>
- <resource uri="config://spring/objects"/> </context>
- <objects xmlns="http://www.springframework.net">
- ...
- </objects>
- </spring>
- </configuration>
我们也可以在配置文件中为IApplicationContext注册自定义的资源处理器、schema解析器、类型转换器和类型别名等等。
本文主要来自《Spring.NET中文手册》。