写点什么

常用 Flex IOC 框架比较分析

2009 年 9 月 29 日

IOC(Inversion of Control),也称 DI(Dependency Injection),是近年来在软件开发中变得非常流行的一种设计策略。众多的 Flex 开发者,探索出了诸如 Spring ActionScript、Parsley、Flicc 和 Swiz 这样的 IOC 框架。

什么是 IOC?一言以蔽之,IOC 是一种软件设计模式。借助 IOC,可用一个独立的对象为其他对象的数据成员填充正确的实现,而不是由这些对象自己负责此项工作。这样做的好处有两个。第一,可将对象的数据成员声明为接口,从而将对象与其具体实现分离(即契约式设计,design by contract)。第二,可从对象中删除创建逻辑,可以使对象的用途更为明确。

IOC 容器提供一个框架,你可借此以一致和宣告的形式使用这个模式。将此模式和接口结合起来,可以创建出易于测试、使用灵活的对象。有关 IOC 模式更深入的讨论,请参看 Martin Fowler 的文章《 Inversion of Control Containers and the Dependency Injection pattern 》。

Java 和.NET 的 IOC 框架早已建立,在 Flex 社区,近来也有不小的进展。

本文将讨论 Flex 中的一些 IOC 框架的工作原理、使用方法,并对这些框架进行比较。为了比较方便,我将在同一个工程(ProfileViewer)中使用 Spring ActionScript、 Parsley、Flicc 和 Swiz 这几个框架。

IOC 的概念

一般有两种最常见的对象配置方法:

  • 对象实例化(例如:var myObject = new Object()
  • 对象查找(例如:var myObject = registry.getMyObject()

而利用 IOC,你可在一个独立层中实例化应用程序要用到的对象,并传入它们所需的依赖。具体来说,最常见的实现方法也有两种:

  • Setter 注入(例如:instance.myObject = new Object()
  • Constructor 注入(例如:instance = new Instance( new Object() )

一个 IOC 框架,通常由如下三个部分组成:配置、工厂和注入机制。

配置

我们可以在配置中描述对象之间的关系。最常用的配置描述方法是在文件中声明。这样的文件有时候也被称为上下文文件(context file)。也可以用元数据 / 注释(metadata/annotation),甚至直接在程序中描述配置。/

工厂

工厂负责配置的解析和所有对象的准备工作,程序一旦运行,就可以根据需要取得这些对象。

在经典的 Spring 框架(最流行的 Java IOC 框架)中,所有对象(我称其为客户对象)都由 IOC 容器负责准备,并且它们以接口形式声明自己的依赖。在配置文件中,被声明的依赖都被设置为对应的实现类。

注入机制

所谓注入机制,是指如何将工厂创建的对象实例注入到应用或其他对象。

就 Spring Web 应用而言,注入方法是通过 web.xml 来实现的。Spring 会监听 Web 应用上下文的加载事件,并利用钩子捕获类加载器的行为,从而分离出任何需被创建的对象。此后,若有需要,工厂将实例化对象,并填充它所需的依赖。当然在向应用返回对象之前,这些依赖本身也可能需要实例化。这个过程即所谓的“(将依赖与对象)捆绑在一起”。

在 Flex 中,类的加载原理有所不同,因此捆绑方法也就不同。目前有两种方法:

  • 客户对象直接从工厂请求(已捆绑好的)对象
  • 利用内置的 Flex 事件机制(用于实例化视图)触发注入

到后面我们具体讨论框架时,这些概念会更容易理解。

ProfileViewer 介绍

ProfileViewer 是一个非常简单的应用,只有两个界面(一个登录面板、一个仪表盘),接下来我们就用这个工程比较、讨论四个框架。ProfileViewer 使用了 MVC(Model-View-Controller)架构和 Presentation Model 模式。

说明:我将 ProfileViewer 建立自己过去看到的一些较为流行的设计模式基础上,仅仅是一个例子,使用这些框架肯定还有其他使用方法。如果你觉得我的方法有任何问题,请一定告诉我。我非常乐意根据大家的意见和建议调整改进。

本文所有例子的源代码可从 flex-ioc-examples project 下载。我建议打开这些源码,对照着阅读本文下面的内容时。

高层架构

开发 GUI 应用时,通常会用到 MVC 模式。我们就不在这里深入讨论 MVC 本身的细节了,如果有需要请参看可参看 Model-view-controller

在此之上,我实现了服务层(见图 1)。应用可在这里得到来自后端系统的数据。在本例中,我简化了这个部分的实现。

最后,我使用了 Presentation Model 模式,应用中每个视图都有对应的模型,模型包含了它的状态和逻辑。正常情况下,视图通过绑定表达式响应模型的状态变化。这样,对视图逻辑做单元测试是没有问题的。有关更多细节,请参看 Martin Fowler 对 Presentation Model 模式的说明 Paul Williams 的文章

图 1. 初期架构

架构改进

为把 IOC 框架引入 ProfileViewer,我需将对象实例及其依赖的管理转移到 IOC 层(见图 2)。一些框架支持将事件关联到 Action,藉此可以搭建一个 Controller 层。我将在适当的地方使用框架提供的这些功能。

图 2. 引入 IOC 后的框架

接下来,我主要说明通过引入 IOC,应用中可得到改善的部分。

对象查找

用户登录成功后,应用取回两个对象。这两个对象包含的信息会在不同的视图中展示给用户。当准备仪表盘的表现层模型(DashboardPM)时,我需查找这两个对象实例:

在 MainPM 中:

复制代码
public function set
authenticated( value : Boolean ) : void
{
//..
var locator : ModelLocator = ModelLocator.getInstance();
dashboardPM = new DashboardPM( locator.user, locator.friends );
//..
}

ModelLocator 使用了单例模式,用于存储模型对象。依靠单例,我在应用的任何地方得到都是相同的对象实例,因为仅仅创建一个对象实例。在这种情况下,我可以安全访问User 和Friends,因为在任何地方,它们都只有一个实例。

不过,单例也有其不足,比如造成单元测试困难——在测试套件整个存在期内,你都必须关注对象的生命周期。因为单例独立于测试用例,静态存储而不会被当做垃圾收集。

对象传递

弱化应用中单例负面影响的办法之一,是按类的继承层次传递对象。

你可以在DashboardPM 的构造器的实现中看到这一点。它需取得User 和Friends 模型,然后由表现层模型将这些实例传递给自己的子类(尽管实际上只会用到User 对象)。一个对象依赖于另一个实际并不直接使用的对象,这显然是一种糟糕的设计实践。

对于小的例子程序而言,这不会是什么大问题,但随着应用规模的扩张,你可以想象这种方法会带来多大的工作量。它也会给你的类带入本不需要的杂质。如果你能只实例化需要的对象,代码将变得更为干净。

最初的ProfileViewer 的表现层模型被配置成继承结构,利用它可以实现对象的传递;引入IOC 后,这个继承结构就不需要了,我会将其删除。

配置服务层

实现非视图层的配置,是对本例的一个有力支持。在本例中通过LoginDelegate 类来表述,这个类会创建它自有的RemoteObject 实例。

Spring ActionScript

Spring ActionScript 前身为 Prana,因其成熟度高,成为了一个知名框架。

核心概念

任何使用过 Spring 的 Java 或.NET 版本的人,都会很快熟悉 Spring ActionScript。你在运行时加载的配置文件,可以给工厂提供足够信息,用于实例化被应用请求的任何对象。

基本配置

在标准例子工程中使用 Spring ActionScript,需如下三个基本步骤:

  1. 创建文件 application-context.xml
  2. 初始化应用中的工厂对象
  3. 在你的视图层(或其他任何地方),根据需要从工厂获得对象以供使用

对象工厂和对象配置

在 Spring ActionScript 中,对象声明在应用可访问的 XML 文件(通常命名为 application-context.xml)中。此配置文件由 XMLApplicationContext(是 ObjectFactory 的子类)加载。

在本例中,初始化工作由如下两个对象承担:ContextLoader 和 Inject。

ContextLoader 获得应用上下文文件的路径。该文件在 XMLApplicationContext 中加载。在应用初始化部分有:

复制代码
private function init() : void
{
ContextLoader.contextPath = "application-context.xml";
}

ContextLoader 在幕后实现对 Spring ActionScript 上下文的加载:

复制代码
public static function set contextPath( value : String ) : void
{
_contextPath = value;
applicationContext = new XMLApplicationContext( _contextPath );
applicationContext.addEventListener( Event.COMPLETE, handleLoadComplete );
applicationContext.load();
}

接着在需要依赖的视图中,我创建一个 Inject 标签(受一个同事在 Parsley 中实现的启发)。利用这个标签,我可以很方便的声明我需将何种依赖添加到该视图。例如,在应用启动时,我有如下代码:

复制代码
<springActionscript:Inject<br></br>property="pm"<br></br>objectId="{ ContextIds.MAIN_CONTAINER_PM }"/><p><springActionscript:Inject</p><br></br>property="controller"<br></br>objectId="{ ContextIds.CONTROLLER }"/>

这将向 XMLApplicationContext 请求一个 ID 为CONTROLLER的对象,并将它赋给视图中的成员变量 controller。

这是在视图层获取对象的好办法。

说明:Christophe Herreman 曾撰文说明如何用 metadata 实现上述类型的注入(类似 Swiz 框架),但这种方法有性能问题,因为要读取元数据,视图需序列化为 XML。

设置控制器

Spring ActionScript 已计划发布一个支持 MVCS 的的扩展版。但在目前版本中,我将实现一个自有的控制器,并利用 Spring ActionScript 将处理程序挂接到事件源。

在最初的程序中,控制器会监听所有事件。当它截获到一个事件后,会查找所有处理器,筛选出能处理这个事件的对象。在经过修改后的例子中,不再监控整个显示列表,转而在 application-context.xml 中将事件源和事件处理器配对。

为此,我增加了一个新类 ControllerPair,它负责事件源和处理器的配对。所有对被传递给 SimpleController,并在它的init()函数中初始化每个对。

复制代码
<object id="controller" class="com.adobe.login.control.SimpleController"><br></br><method-invocation name="init"></method-invocation><br></br><property name="controllerItems"><br></br><array><ref>controllerItem</ref></array><br></br></property><br></br></object><p><object id="controllerItem” class="com.adobe.login.control.ControllerPair"></p><br></br><property name="dispatcher" ref="loginPM"/><br></br><property name="handler" ref="handler"/><br></br></object>

请注意其中的method-invocation标签,我们用它来指定对象被创建后马上自动调用的函数。在这里,被自动调用的函数是init(),它负责将事件派发者绑定到事件处理器。

表现层模型的注入

在非 IOC 版的 ProfileViewer 中,为了实现对象的传递,表现层模型被配置为继承式结构。在 IOC 版中,我将删除此结构,以便每个表现层模型都能被配置为对应的视图。

尽管这样做,应用更易于配置和测试,但也有其缺点。在某些情况下,要实现离散的表现层模型之间的交互,需要做不少工作。

Spring ActionScript 同时支持 setter 和 constructor 两种形式的注入。我更倾向于使用 construtor 注入,因为它可以完全暴露对象运作所需的全部依赖。如下是 DashboardPM 的配置:

复制代码
<object id="dashboardPM" class="com.adobe.dashboard.presentationModel.DashboardPM"><br></br><constructor-arg ref="user"/><br></br></object>

在 XML 中声明构造函数的参数时,顺序应和对象的构造函数所期望的参数顺序相同。上面代码中的 ref 表示引用在上下文中声明的另一个对象,在这里即 User。

配置服务层

LoginHandler 引用了代理对象,代理对象又依赖于另一个远程对象,该远程对象可以调用后端系统的功能。

下面,我们用 setter 完成这些对象的配置。需通过 setter 传入的实例包括代理对象和 AuthenticationClient(这是一个用于检查用户是否已登录的接口)。MainPM 具体实现了 AuthenticationClient。

在这里,我将代理设计为存根,依赖于一个远程对象。配置如下:

复制代码
<object id="handler" class="com.adobe.login.control.handler.LoginHandler"><br></br><property name="client" ref="mainPM"/><br></br><property name="user" ref="user"/><br></br><property name="friends" ref="friends"/><br></br><property name="delegate" ref="loginDelegate"/><br></br></object><p><object id="loginDelegate" class="com.adobe.login.service.LoginDelegate"></p><br></br><property name="remoteObject" ref="remoteObject"/><br></br></object><p><object id="remoteObject" class="mx.rpc.remoting.RemoteObject"></p><br></br><property name="destination" value="SPRING_ACTIONSCRIPT_DESTINATION"/><br></br></object>

总结

Spring ActionScript 是一个优秀的、成熟的、开发活动十分活跃的 IOC 框架。它使用的术语,应该说是任何用过 Spring 框架的人都熟悉的。

以 XML 形式声明对象存在一个问题,即在 XML 中声明一个类,并且这个类没被包含在 SWF 中(因为在你的应用中没有对它的直接引用)时,Flash Player 会在运行时抛出异常。其解决办法是创建一个 ActionScript 类,声明它对上下文 XML 的依赖,并将此类包含在应用中。

Parsley

Parsley 也是一个成熟的 IOC 框架,最初灵感来源于 Spring。它近期经历过一次较大规模的重写。新版本支持一些本地 Flex 特性,如绑定和元数据,使你在配置你的工程时有更多更好的选择。

核心概念

Parsley 的核心概念是源自于 Spring 的上下文,也即应用的依赖注入的配置。

Parsley 的配置现在支持多种形式,其中包括 XML 和 MXML。你可以使用本地的 MXML 标记或 Parsley 库提供的自定义 MXML 标签。Parsley 使用元数据标签实现对注入机制的支持,这和 Swiz 框架是类似的。

Parsley 还支持消息模式。基本不需代码干预,你就能将你的对象配置为事件源或事件处理器。在这个例子中,我会用这个特性替代 Controller 模式。

基本配置

Parsley 的配置分三个基本步骤:

  1. 创建 Config.mxml 文件。
  2. 在应用的根部初始化一个 Context 对象。
  3. 在你的视图中,用 Inject 元数据实现依赖的注入。

准备配置文件的方法有多种,不过在这个例子中,我使用支持本地标记和 Parsley 标签的 MXML 文件。这种方法的好处是在编译时就将类引入,当然这样一来,也就不能直接修改已被编译的应用的配置了。

对象工厂和对象配置

在 Config.mxml 中,你能看到应用中用到的从域模型到代理的所有对象。声明这些对象的方式有两种:

  1. 标准的 MXML
  2. 使用 Parsley 的对象定义标签

在后面的内容中,我将详细介绍这种方法。

设置控制器和 LoginHandler

我在这里不再使用自己编写的控制器,转而使用 Parsley 的消息系统(其设计决定了它对你编写的对象的影响很小)。具体是用元数据来实现。Parsley 将事件源绑定到事件处理器,需要一个在上下文可见且具有元数据的对象。

在这个例子应用中,LoginPM 是事件源,LoginAction(从 LoginHandler 重命名而来)是事件处理器。

如下代码摘自 LoginPM:

复制代码
[Event( name="LOGIN", type="com.adobe.login.control.event.LoginEvent")]
[ManagedEvents("LOGIN")]
public class LoginPM extends EventDispatcher
{
...
public function login() : void
{
var event : LoginEvent = new LoginEvent( username, password );
dispatchEvent( event );
}
}

让 LoginPM 成为事件源需要三个要素:Event元数据标签、ManagedEvents元数据标签,以及EventDispatcher#dispatchEvent。三者当中,只有ManagedEvents是 Parsley 扩展而来。Event元数据仅为习惯做法,事件的实际派发工作是由dispatchEvent完成的。Parsley 将通过ManagedEvents决定它要处理哪个事件,并将该事件委托给事件处理器。

如下代码摘自 LoginAction(已经被配置为事件处理器): ```
public class LoginAction implements IResponder
{

[MessageHandler]
public function execute( event : LoginEvent ) : void
{

}
}

复制代码
因为我为这个函数补充了 MessageHandler 元数据,Parsley 将把这个对象 / 函数当做类型为 LoginEvent 的所有事件的监听器。
要让这些对象对 Parsley 可见,可在传入 FlexContextBuilder 的配置文件内声明这些对象,或在视图中使用 Configure 对象。
### 表现层模型的注入
和其他例子一样,我已将表现层模型的继承结构去除。相关原因请参看 [Spring ActionScript](http://www.adobe.com/devnet/flex/articles/ioc_frameworks_04.html)。
Parsley 支持 setter 和 constructor 两种注入方法。像我在 Spring ActionScript 例子中提到的那样,我更倾向于使用 constructor 注入,因为它可以暴露出对象运作所需的全部依赖。如是是 DashboardPM 的配置:
`<spicefactory:Object type="{ DashboardPM }"/>`如果你的对象构造函数需要参数,则应该用 Object 标签予以声明,因为这样的参数在本地 MXML 中是不支持的。
要完成此构造函数,你需向类中添加一些元数据:

[InjectConstructor]
public class DashboardPM
{
public var user : User;

public function DashboardPM( user : User )
{
this.user = user;
}

}

复制代码
这里的元数据标签`InjectConstructor`,表示要求`Parsley`给`DashboardPM`的构造函数注入一个类型为 User 的、已声明过的对象。
若使用 setter 注入,你仅需在类中增加元数据标签`Inject`。例如,我在 Config 中用标准 MXML 声明`SummaryPM`:
`<dashboard:SummaryPM/>`接着,在类文件中有如下代码:

public class SummaryPM
{
[Inject]
public var friends : Friends;

}

复制代码
这里的 Inject 标签表示需将一个类型为 Friends 的实例注入到 SummaryPM。
### 总结
经过其他一些框架的不断启发,新版本的 Parsley 已发展成为一个完整的 IOC 框架。它还支持模块式开发和上下文卸载。在模块化 Flex 应用开发日益盛行的今天,这无疑是一个十分重要的特性。
## Flicc
- 框架:Flicc
- 网站:<http://flicc.sourceforge.net/>
- 开发者:Mike Herron
- 版本:0.5
- 许可:开源
- 配置:MXML
在 IOC 领域,Flicc 是一个不太知名的后来者。它的配置方法(利用 MXML 文件)略有不同。它在 MXML 中有自己的对象定义标记,借此可将预先存在的对象传入工厂,并添加依赖(如传入一个视图)。
在 MXML 中声明依赖的好处,是依赖在编译时就被包含到应用中,这样可避免在应用运行时由于依赖的丢失造成异常。当然其缺点也是明显的,即不重新编译程序,依赖就不能改变。
### 对象工厂和对象配置
在 Filcc 中,将 Configure 标签添加到视图后,可以传入要配置的实例。另外也可以传入已经存在的实例并进行配置——和我在 Spring ActionScript 实现中使用过的 Inject 标签类似。
### 基本配置
1. 创建一个从 MXMLObjectFactory 继承的配置类。
2. 创建一个 Filcc 实例并传入配置。
3. 在需要的地方,将 Configure 标签添加到你的视图中。









复制代码
`MxmlObjectFactory`标签被添加到应用的根部。`MxmlObjectFactory`上一层的 FliccListener 标签,表示要求 Flicc 拣选出由`Configure`标签派发的应用程序显示列表中的事件。`Config.mxml`是我的配置文件。
### 设置控制器
和 Parsley 类似,Filcc 支持在配置文件中将事件和对象绑定,尽管它并不使用控制器这个概念。
我利用这种方法将控制器绑定到事件源(即 LoginPM)。当 LoginPM 派发它的事件时,事件被控制器截获,随后调用对应的处理器。

























复制代码
我们在控制器中查找给定类型的事件,并触发 execute 方法:

public function handleEvent( event : Event ) : void
{
getHandlerForEventType( event.type ).execute( event );
}

复制代码
### 表现层模型的注入
同样,在这个例子中,我删除了表现层模型间的继承结构。Filcc 也支持 setter 或 constructor 这两种注入方法。
Filcc 有两类基本的对象标签:`Component`和`Object`。`Component`用于描述你想配置的、已经存在的对象。`Object`则用于创建新实例。例如:









复制代码
和 Spring ActionScript、Parsley 类似,你应按对象期望的顺序声明对象构造函数的参数。Ref 表示引用声明在同一个上下文中的其他对象,该对象的标识用`to`属性表示。
`Component`和`Object`类似,但仅能依靠`setter`注入,因为`Component`描述的是已经存在并被传入`Flicc`的对象:















复制代码
如上的 Component 表示主应用,具有两个依赖:一个控制器、一个 pm 变量。
### 配置服务层
LoginHandler 依赖于 LoginDelegate,后者又依赖于 RemoteObject。
配置如下:













FLICC_DESTINATION



复制代码
上述代码声明了一个新的 LoginDelegate 实例,并填充了它对 RemoteObject 的依赖。
### 总结
Flicc 不同于前面讨论过的两个框架,它的声明方式为 MXML。当然这只是一个形式,所有框架的基本原理都是相同的。
在 MXML 中定义配置,可节省开发时间,因为类被编译进应用,运行时就不必花时间处理外部文件的载入和解析。因其 API 和先前两个框架有所不同,要熟练运用可能得花点时间。
## Swiz
** 说明 **:本文中使用的 Swiz 不是最新,因此在这里讨论的使用方法可能不适用于新的版本。建议在开发前访问 Swiz 框架的网站,查阅最新文档。同时,我也正在 Swiz 最新版基础上,更新本文的这部分内容。
- 框架:Swiz
- 网站:<http://code.google.com/p/swizframework/>
- 开发者:Chris Scott
- 版本:0.0.5
- 许可:开源
- 配置:MXML + Metadata
Swiz 也是一个新兴的 IOC 框架,但不仅限于此。它旨在发展成为一个完整的 RIA(Rich Internet Application)架构下的解决方案。Swiz 利用 MXML 定义对象,但有着不同的注入机制。
### 核心概念
Swiz 也有一个加载进 Swiz 实例的配置文件。此配置文件使用标准的 MXML 声明格式,其利弊共存。好处是类被自动加载为类路径的一个部分,可以利用数据绑定实现对象依赖的注入。其缺点是用 MXML 声明对象时,不能创建构造函数中带参数的对象。当然你可以在 ActionScript 块中完成相关初始化工作,但就因此失去了完全依靠声明标记所体现出的表达质量了。
Swiz 会根据注入的定义,从类中读取元数据,并由此判定要在何地注入何种对象。是 [Google Guice](http://code.google.com/p/google-guice/) 让这种方法在 Java 用户中流行起来的。
有了元数据,你的对象包含的信息更为丰富,你的配置文件也更清晰。
### 基本配置
1. 将元数据参数添加到编译器
2. 创建 Bean 文件
3. 将元数据添加到你想注入依赖的类中
在 Swiz 中,你可在应用程序的根部加载 Bean 集合:

private function onPreInitialize() : void
{
Swiz.getInstance().loadBeans( [ AppBeans ] );
}

复制代码
获得具体的 Bean,在 Swiz 中就有两种方法了:
`Swiz.getBean( "loginHandler" )`或使用元数据:

[Autowire(bean=“dashboardPM”)]
public var pm : DashboardPM

复制代码
有关其他可能的方法,请参看 Swiz 文档。但若使用元数据注入,需记住的是,类必须包含在显示列表中,否则注入无效。上述代码来自于 DashboardPanel。
在底层,Swiz 会监听被添加到显示列表的全部对象,并通过反射判断这些对象是否包含注入元数据。为读取元数据,这些对象必须被序列化为 XML,因此存在性能问题。
### 设置控制器
Swiz 在指定通过 Swiz 内部机制派发的事件的处理函数方面做得很好。
我在 LoginHandler 中增加如下元数据:

[Mediate(event=“LOGIN”, properties=“username,password”)]
public function login( username : String, password : String ) : void

复制代码
然后在事件源(LoginPM)如按如下派发事件:
`Swiz.dispatchEvent( new LoginEvent( username, password ) );`至此,将事件源挂接到处理函数需做的全部工作都完成了。
### 表现层模型的注入
和前面几个框架一样,我在这里仍将表现层模型配置为无继承结构。
定义如下:

<local:MainPM id=“mainPM”/>

<login:LoginPM id=“loginPM”/>

<presentationModel:DashboardPM id=“dashboardPM”/>

复制代码
在类中用标准 MXML 定义注入:

public class LoginHandler implements IResponder
{
[Autowire(bean=“mainPM”)]
public var client : AuthenticationClient;

[Autowire]
public var user : User;

[Autowire]
public var friends : Friends;

[Autowire(bean=“loginDelegate”)]
public var delegate : LoginDelegate;

}

复制代码
** 说明 **:如果待注入依赖的成员和 Bean 对象同名,那么就不需要显式指定 Bean 名。比如上例中,user 和 friends 能自动分别得到名字为“user”和“friends”的 Bean。
### 配置服务层
LoginHandler 依赖于 LoginDelegate,LoginDelegate 又依赖于 RemoteObject。和注入表现层模型类似,利用元数据如下配置服务层:

public class LoginDelegate
{
[Autowire(bean=“loginHandler”)]
public var responder : IResponder;

[Autowire]
public var remoteObject : RemoteObject;

//…

复制代码
### 总结
Swiz 中定义注入的方法与众不同,其配置和其他框架相比更为简单。
Swiz 通过反射获取对象的信息,在大型应用中,无疑会产生不小的性能问题。不知道 Swiz 在未来是否会允许用户选择性启用或禁止这类行为,但目前已经有 [Aral Balkan](http://aralbalkan.com/1960) 和 [Christophe Coenraets](http://coenraets.org/blog/2009/03/the-Spring%20ActionScript-framework-%E2%80%93-part-2-autowiring/) 提供了一些解决方案。
## 总结
本文简要介绍了一些比较知名的 Flex 框架下的 IOC 容器,未被提及的有 [Mate](http://mate.asfusion.com/) 和 [SmartyPants](http://code.google.com/p/smartypants-ioc/)。Mate 支持 IOC,但不仅限于此。我最初打算在本文中准备一个 Mate 的例子,但后来觉得还是先深入学习后再写。写完这个例子后,我会在 [Google code](http://code.google.com/p/flex-ioc-examples/) 上公布。SmartyPants 和 Swiz 类似,也是利用元数据表述注入,值得一看。
本文是在 Flex 应用中使用 IOC 的入门读物,另外也是对各种框架做一比较,希望对你有所帮助。文章不能兼顾到这些框架的方方面面,建议你阅读它们的文档,了解更多细节。
- - - - - -
给 InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 [editors@cn.infoq.com](mailto:editors@cn.infoq.com)。也欢迎大家加入到 [InfoQ 中文站用户讨论组](http://groups.google.com/group/InfoQChina) 中与我们的编辑和其他读者朋友交流。
2009 年 9 月 29 日 08:479060
用户头像

发布了 26 篇内容, 共 66315 次阅读, 收获喜欢 1 次。

关注

评论

发布
暂无评论
发现更多内容

Week 11 学习总结

Jeremy

终于可以职业规划了么?

escray

学习 面试 面试现场

用python给女朋友做一个歌曲词云图

我是程序员小贱

区块链政策区域特征分明 产业园区渐成聚集效应

CECBC区块链专委会

区块链 新基建

数据库快速迁移10亿级数据

架构师修行之路

高并发系统设计 数据库优化

搞一搞Elasticsearch

北漂码农有话说

对于结果不同程度的追求,决定了这个人的身价

非著名程序员

程序员 个人成长 思维模型 结果思维

Week 11命题作业

Jeremy

小白程序员成长之路-准备篇

桃夭十一里

盲打练习 在线打字

Apache Pulsar 社区周报:08-08 ~ 08-14

Apache Pulsar

Apache Apache Pulsar 消息系统

区块链在新冠病毒爆发中将加速发展

CECBC区块链专委会

区块链技术 供应链 食品追溯

架构设计篇之云计算服务设计与决策

小诚信驿站

云计算 刘晓成 企业架构和云服务 SaaS/IaaS/PaaS

特性预览:Apache 顶级项目 Apache Pulsar 2.6.1 版本即将发布

Apache Pulsar

Apache Apache Pulsar 消息系统

简单交互式页面的思考(C)

Alex

指针 C语言 交互设计

如何通过技术面试?

escray

学习 面试 面试现场

我是合适的人选么?

escray

学习 面试 面试现场

迟到的"松鼠"

许学文

个人感悟

公司想要大龄程序员么?

escray

学习 面试现场

为什么考研,考研能给你带来什么?说说我的感受!

我是程序员小贱

辗转相除法求最大公约数(C语言实现)

InfoQ_3f366696ed0c

C语言

学习笔记丨Makefile的基本编写与优化

Liuchengz.

c Linux makefile

四十不惑,准备面试

escray

学习 面试现场

Flink的2种部署模式-2

小知识点

scala flink 大数据技术

兄弟,不要偷看人家摄像头

我是程序员小贱

企业品尝新基建的美酒前,需要名为NetEngine 8000的酒杯

脑极体

免费开源看板软件Wekan安装与使用记录

emuqi

Docker 效率工具 wekan 看板 任务管理

Python中的bytes、str以及unicode区别

王坤祥

Python Python PEP

firewalld 常用指令

wong

Firewalld

究竟要找什么样的工作?

escray

学习 面试 面试现场

我喜欢的工作,喜欢我么?

escray

学习 面试 面试现场

大数据技术发展(三):Spark 代替 Hadoop ? Spark Or Flink ?

抖码算法

Java 大数据 flink hadoop spark

飞猪Flutter技术演进及业务改造的实践与思考

飞猪Flutter技术演进及业务改造的实践与思考

常用Flex IOC框架比较分析-InfoQ