`
whilew
  • 浏览: 21280 次
文章分类
社区版块
存档分类
最新评论

Parsley 框架简介

 
阅读更多

原文地址:http://blog.chinaunix.net/uid-122937-id-143055.html

配置和初始化 Parsley 框架通常包括以下步骤:

  • 第 1 步: 告诉 IOC 容器哪些类需要被它管理. 这可以使用 MXML, XML 文件或者 ActionScript 来做.这三种机制会在跟着下来的章节中说明.
  • 第 2 步:配置容器的服务,如:依赖注入或者每个单独类的消息 .这可以在第 1 步中你选择的配置机制中完成 (例如:使用 MXML 或者 XML 配置标签) 或者 - 通常情况下在类中使用 AS3 Metadata 标签.
  • 第 3 步: 初始化 IOC 容器(通常在程序开始时). 在 Parsley 2 中通常只需一行代码. 可以查看下面例子.

3.1 使用 AS3 Metadata 进行配置

AS3 Metadata 标签可以用来配置像依赖注入或者消息等服务. 它们可以放到由 Parsley管理的任何类中去.使用 metadata 标签的配置可以与 XML 或者 MXML 的配置相结合. 几乎每个 metadata 标签每有与它相对应的 MXML 和 XML 配置标签. 为了避免冲突, MXML 和 XML 配置会优于 Metadata 配置, 因此你可以覆盖 metadata 配置而不必对类的代码进行修改.

每个 metadata 标签和它们的属性会在相应的章节的相关例子中说明:

3.2 MXML 配置

这种配置只能被 Flex 程序使用. 其它的配置在 Flex 和 Flash 程序中都可用.

假定你要配置以下两个类:

      package com.bookstore.service {
          class LoginServiceImpl implements LoginService {
               public var timeout:int;
               public function login (username:String, password:String) : void {
                     // execute service    
               }
          }
     }
     package com.bookstore.actions {
         class LoginAction {
            [Inject]
            public var service:LoginService
    
            [MessageHandler]
            public function handleLoginEvent (event:LoginEvent) : void {
                service.login(event.username, event.password); 
            } 
         }
    }

你可以见到使用 metadata 已经配置了几个功能. 查看第4章依赖注入第5章消息系统了解这些功能的细节.

MXML 配置文件

我们需要告诉容器管理这些类并创建以下 MXML file:

    <mx:Object 
        xmlns:mx="http://www.adobe.com/2006/mxml"
        xmlns:services="com.bookstore.services.*"
        xmlns:actions="com.bookstore.actions.*">
    
        <services:LoginServiceImpl timeout="3000"/>
    
        <actions:LoginAction/>
    
    </mx:Object> 

请注意我们并不需要导入 Parsley . 只需要在 MXML 中添加普通的 object 标签. 除了 metadata 标签你还可以使用 MXML 标签进行其它配置 , 比如上面例子的 timeout 值.


框架的初始化

最后你需要初始化容器. 假设你将配置保存在 BookstoreConfig.mxml, 你可以使用以下命令将它初始化:

         FlexContextBuilder.build(BookStoreConfig);

在许多程序中,以上的一行代码便是你唯一直接使用的 Parsley API.你可以在某些类的方法上添加 [PostConstruct] 标签让程序开始时执行这些方法. 查看第6.5章Context 周期了解细节.

理论上你也可以使用 Parsley 的 API:

          var context:Context = FlexContextBuilder.build(BookStoreConfig);
          var initializer:BookStoreInitializer = context.getObjectByType(BookStoreInitializer) as BookStoreInitializer;
          initializer.execute();

但这种用法并不推荐使用. 在一般的程序中都无需直接使用 Parsley 的 API. 只有在 Parsley 基础创建你自己的框架时才使用.


使用 Parsleys MXML 标签

以上的 MXML 配置还可以使用 Parsley 标签来代替 object 标签:

<mx:Object 
    xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns="http://www.spicefactory.org/parsley">
    
    <mx:Script>
        <![CDATA[
            import com.bookstore.services.*;        
            import com.bookstore.actions.*;        
        ]]>
    </mx:Script>
    
    <Object type="{LoginServiceImpl}">
        <Property name="timeout" value="3000"/>
    </Object>
    
    <Object type="{LoginAction}"/>
    
</mx:Object> 

使用这些特殊的标签比普通的标签有其它的功能. 两种方式都有优缺点:

普通 MXML 标签的优点:

  • 简单、可直接使用.
  • 无需知道 Parsley 的配置标签.
  • 编译器会检查属性值的类型.

Parsley MXML 标签的优点:

  • 允许使用构造器注入 . 从封装性方面来看,这是依赖注入的最干净的方式. 使用普通标签时你不能使用构造器注入的方式,因为在那种情况下 MXML 编译器生成了对象的创建代码并且 Parsley 只能在对象实例化后才得到该对象. 当使用普通标签时,你的类需要一个没有参数的构造方法.
  • 允许定义对象为 lazy的 (<Object lazy="true" type="..."/>) ,也就是说在你第一次使用该对象之前它不会被初始化和配置.
  • 允许将一个对象配置成非单例的(<Object singleton="false" type="..."/>). 也就是说,每次从容器取这个对象或者将这个对象注入其它对象时,容器都会创建一个新的实例.
  • 允许使用自定义标签. Parsley 2 是非常容易扩展的. 你可以使用一个类来创建一个自定义的扩展,然后将它作为自定义的 metadata 标签, MXML 或者 XML. 你可以查看 第11章扩展本框架中的例子.

3.3 XML 配置文件

在以下情况中,外部 XML 文件是 MXML 之外的另一个合适的选择:

  • 你的配置经常发生改变而你又不想再进行编译.
  • 配置文件可以被不懂编程的人进行修改.
  • 你没有在使用 Flex.

当然你也可以在某部分配置中使用 XML 文件而仍然使用 MXML 配置来注入你的核心服务. 查看第3.5章将多个配置机制整合了解细节.

上面例子的 MXML 配置也可以配置成以下的 XML 配置:

<objects 
    xmlns="http://www.spicefactory.org/parsley"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.spicefactory.org/parsley 
        http://www.spicefactory.org/parsley/schema/2.0/parsley-core.xsd"
    >
    <object type="com.bookstore.services.LoginServiceImpl">
        <property name="timeout" value="3000"/>
    </object>
    
    <object type="com.bookstore.services.LoginServiceImpl"/>
</objects>

一般的 XML 配置跟使用 Parsley MXML 标签的 MXML 配置非常类似. 在底层它们实现的作用是一样的.唯一的不同是 XML 配置需要使用 XML 规范,标签不可以大写并且属性名需要使用-,如: targetProperty 要写成target-property .

假定你的配置文件是config.xml,初始化还是使用一行代码:

           XmlContextBuilder.build("config.xml");

编译在 XML 中配置的类

你需要注意的是:与在 MXML 中配置的类不同,XML 中配置的某些类如果没有被使用的话,它不会被编译到你的 SWC 或者 SWF 文件.

解决这个问题有三种方法(即:你想要把没有使用的类也要编译到 SWC 或者 SWF 文件):

  • 在你的代码中添加这些类的引用,即使你并不需要它.
  • 如果你想将这些类作为库使用, 将它们编译到一个 SWC (使用compc你可以将整个源代码文件夹包含到 SWC 文件) 然后使用mxmlc编译器中的-include-libraries选项将整个 SWC 包含到你的 SWF 文件.
  • 你可以使用mxmlc编译器的-includes选项来包含某些类.

3.4 ActionScript 配置

如果你只认识 Flex IOC 容器的话,你可能不熟悉这种方式. 它跟 Java 的 Spring 框架中的 JavaConfig 有点相似. 它允许你使用代码的方式来创建要给 Parsley 管理的对象. 我们使用之前例子的那两个类并将它们添加到 IOC 容器中:

package com.bookstore.config {

  class BookStoreConfig {

    public const action:LoginAction = new LoginAction();
    
    public function get service () : LoginServiceImpl {
        var service:LoginServiceImpl = new LoginServiceImpl();
        service.timeout = 3000;
        return service;    
    }

  }
}

我们使用了 ActionScript 来设置 timeout 属性. 无论你使用var,const或者一个 getter 函数来声明对象,这些对象都会被添加到 IOC 容器中.

初始化还是只用一行代码:

            ActionScriptContextBuilder.build(BookStoreConfig);

这个配置模式允许你增加 metadata 标签:

[ObjectDefinition(singleton="false")]
public function get service () : LoginServiceImpl {
    var service:LoginServiceImpl = new LoginServiceImpl();
    service.timeout = 3000;
    return service;    
}

在上面的例子中,每次这个对象被请求时,容器都会调用 getter 函数. 默认的 singleton 属性是true, 所以如果没有 metadata 标签的话 Parsley 只调用这个方法一次并把这个实例缓存起来,对于所有的注入都是重复使用同一个实例.

3.5 将多个配置机制整合

自Version2.2后,配置管理机制允许指定实例在运行期间,作为容器的一部分:

    <parsley:ContextBuilder>
         <parsley:FlexConfig type="{ServiceConfig}"/>
         <parsley:FlexConfig type="{ControllerConfig}"/>
         <parsley:XmlConfig file="logging.xml"/>
         <parsley:RuntimeConfig instances="{[instance1, instance2]}"/>
    </parsley:ContextBuilder>

如果你需要指定ID,也可标注子标签:

<parsley:ContextBuilder>
    <parsley:FlexConfig type="{ServiceConfig}"/>
    <parsley:FlexConfig type="{ControllerConfig}"/>
    <parsley:XmlConfig file="logging.xml"/>
    <parsley:RuntimeConfig>
        <parsley:Instance id="obj1" instance="{instance1}"/>    
        <parsley:Instance id="obj2" instance="{instance2}"/>    
        <parsley:Instance id="obj3" instance="{instance3}"/>    
    </parsley:RuntimeConfig>
</parsley:ContextBuilder>

在RuntimeConfig标签中添加的对象与之后添加的DynamicObjects不同之处在于,前面的作为根对象,可注入到其它对象中,因为它们在上下文构建时已指定。

你甚至可以使用普通的<Object>为内部标签

<parsley:ContextBuilder>
    <parsley:FlexConfig type="{ServiceConfig}"/>
    <parsley:FlexConfig type="{ControllerConfig}"/>
    <parsley:XmlConfig file="logging.xml"/>
    <parsley:RuntimeConfig>
        <parsley:Instance id="obj1" instance="{instance1}"/>    
        <parsley:Instance id="obj2" instance="{instance2}"/>    
        <parsley:Object id="obj3" type="{LoginInterceptor}"/> 
            <parsley:MessageInterceptor method="intercept" type="{LoginEvent}"/>
        </parsley:Object>    
    </parsley:RuntimeConfig>
</parsley:ContextBuilder>

你也可以用编码方式进行配置:

   var rcp:RuntimeConfigurationProcessor = new RuntimeConfigurationProcessor();
     rcp.addInstance(instance1, "id1");
      rcp.addInstance(instance2, "id2");
      rcp.addClass(MyClass, "id3");

      var builder:CompositeContextBuilder = new DefaultCompositeContextBuilder(viewRoot);
      FlexContextBuilder.merge(MainConfig, builder);
      builder.addProcessor(rcp);
      builder.build();

3.6 混合多个配置方式

虽然你可能在大多数程序中偏好于只用一个配置, 你不必一定要这样做. 你可以将本章所讲的配置进行组合使用.

对于一种配置,你也可以将它分成几个文件. 然后使用buildAll方法:

          FlexContextBuilder.buildAll([BookStoreServices, BookStoreActions]);
          XmlContextBuilder.buildAll(["services.xml", "actions.xml"]);
          ActionScriptContextBuilder.buildAll([BookStoreServices, BookStoreActions]);

你也可以使用CompositeContextBuilder类将它们合并在一起:

          var builder:CompositeContextBuilder = new CompositeContextBuilder();
          FlexContextBuilder.merge(BookStoreConfig, builder);
          XmlContextBuilder.merge("logging.xml", builder);
          builder.build();	

这种方式也是很简单的: 你只需创建一个CompisiteContextBuilder类的实例并把它放到各个context builder 类的merge方法中.

以上所有的例子最终的结果都是一个 Parsley Context. 无论你有多少个配置文件,结果都是一样的.

对于大型和复杂的程序,你想要创建模块化 Contexts, 即多个配置不是合并到一个 Context, 以便它们可以根据需要进行加载和缷载. 对于模块化的程序你可以阅读第8章使用 Flex Modules第6.4章Modular Contexts.

最后,如果你想要创建你自己的配置模式并将它与现有的配置方式无缝地结合的话, 你可以创建ObjectDefinitionBuilder接口的实例并将它们传入到CompositeContextBuilder.addBuilder. 查看第11章扩展本框架了解细节 .

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics