产品战略专家梁宁确认出席AICon北京站,分享AI时代下的商业逻辑与产品需求 了解详情
写点什么

常用 Flex IOC 框架比较分析

  • 2009-09-29
  • 本文字数:10392 字

    阅读完需:约 34 分钟

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-09-29 08:479647
用户头像

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

关注

评论

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

如何借助CDC快速实现实时数据传输?

RestCloud

数据同步 ETL CDC

IPQ8074 Industrial Router with QCN9074/QCN9024 WiFi Network Card - Excellent performance and comprehensive coverage

wifi6-yiyi

QCN9074 IPQ8074

七个 LLM 的狼人杀之夜;马斯克的星链残骸会“砸死人”?OpenAI 安全漏洞曝光丨RTE开发者日报 Vol.66

声网

mac软件推荐:CAD迷你看图中文版

胖墩儿不胖y

Mac软件 cad软件 CAD看图工具

深度学习应用开发示例之像素分割

矩视智能

深度学习 像素分割

软件测试/测试开发丨Postman实战练习 学习笔记

测试人

Python 软件测试 测试开发

以效率为导向:用ChatGPT和HttpRunner实现敏捷自动化测试(二) | 京东云技术团队

京东科技开发者

自动化测试 敏捷测试 HttpRunner ChatGPT 企业号10月PK榜

漱玉平民大药房:多元化药店变革的前夜

TiDB 社区干货传送门

OpenHarmony社区运营报告(2023年9月)

OpenHarmony开发者

什么是 Merge Queue,为什么要使用它?

高端章鱼哥

merge 合并队列

浅析斐波那契数列在代码中的应用

emanjusaka

Java 后端

可完全替代FTP的文件传输工具大集合

镭速

文件传输工具 替代FTP FTP传输文件

TiDB x Bolt丨超强可扩展性与弹性助力超 1 亿用户畅享出行服务

TiDB 社区干货传送门

Java基础面试题【七】线程池

派大星

Java 面试题

负载均衡详解

天翼云开发者社区

负载均衡 服务器

百度飞桨AI4S亮相全国动力学设计与反问题研讨会,助力汽车底盘智能设计

飞桨PaddlePaddle

深度学习 AI for Science

MySQL的index merge(索引合并)导致数据库死锁分析与解决方案 | 京东云技术团队

京东科技开发者

MySQL 数据库 索引 企业号10月PK榜

TiDB x Catalyst丨秒级洞悉数据价值,TiDB 帮助“客户成功 SaaS 厂商”提升用户体验

TiDB 社区干货传送门

打造次世代分析型数据库(六):如何从零实现向量化引擎

腾讯云大数据

数据库

开放原子开源基金会联合主办的2023 CCF中国开源大会即将开幕

开放原子开源基金会

开源 CCF

测试过程效率的提升和演变

老张

软件测试 研发效能 质量保障

Postman 调试 WebSocket 接口完整指南

Liam

Postman websocket 接口调试 测试工具 API 测试

企业如何选择安全又稳定的文件传输协议

镭速

大文件传输 文件传输协议

如何开发区块链应用程序:分步指南

区块链软件开发推广运营

交易所开发 dapp开发 区块链开发 链游开发 NFT开发

Trino容错模式深度测评与思考

华为云开发者联盟

大数据 后端 华为云 华为云开发者联盟 交互式分析

TiDB x 安能物流丨打造一栈式物流数据平台

TiDB 社区干货传送门

使用eBPF加速阿里云服务网格ASM

阿里巴巴云原生

阿里云 云原生 服务网格

TiDB v7.4.0 版本上线啦!看看有没有你想要的功能上线啦!

TiDB 社区干货传送门

TiDB 7.4 发版:正式兼容 MySQL 8.0

TiDB 社区干货传送门

数据如何同步到云服务器

天翼云开发者社区

云计算 数据迁移

云网络对等连接产品的高可用保证

天翼云开发者社区

网络 对等连接

常用Flex IOC框架比较分析_Java_Ed Eustace_InfoQ精选文章