守望者--AIR技术交流

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

搜索
热搜: ANE FlasCC 炼金术
查看: 2897|回复: 3

[ActionScript] SwiftSuspenders 1.6 浅出深入 浅出

[复制链接]
  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    52620
    钢镚
    1422

    开源英雄守望者

    发表于 2015-1-10 20:59:09 | 显示全部楼层 |阅读模式
    本系列文章来自:http://sswilliam.blog.163.com/blog/static/189696383201175114948372/


    前言

    写这篇文章的原因是想研究一下一个非常有意思的AS3 MVC框架robotlegs。在研究的过程中发现了robotlegs是一个基于依赖注入(DI)的框架。而帮助robotlegs实现依赖注入的就是这篇文章要介绍的一个轻量级的依赖注入框架swiftsuspernders

    Swiftsuspernders是一个快速的、轻量的AS3依赖注入解决方案。AS3已经有了很多依赖注入的框架,如SpringSmartyPants。这两个框架的功能都很强大,但是很多情况下其实用不到那么强大的功能。Swiftsuspernders相比之下提取了最核心的依赖注入的功能。通过阅读了Swiftsuspernders的代码,发现有许多值得学习的地方,同时也有一些在平常编写AS3代码时很少触及的部分,因此将这些整理出来进行分享。

    虽然博客很久之前就出现了,但是一直没有接触。也许是人老了想法就变了,最近发现有一个博客,记录一下开发过程中的一些心得和体会,是一个很好的知识积累的过程。一些系统性的教程之类的文章,都会以浅出深入命名。一般这类文章都会包含两个部分:第一个部分是浅出,顾名思义就是以浅显易懂的方式出师。主要是对某个技术的快速入门。如这篇《Swiftsuspenders浅出深入》,浅出部分会针对Swiftsuspenders做一个快速入门。一般这部分会参考很多教程之类的文章,基本是一个整理或者翻译的部分。如果涉及版权问题请作者联系,同时我也会将参考的文献列出。一般的开发者看这部分就够了。第二部分是深入,主要是对某个技术的深入挖掘。如果是一些开源项目。基本上会是针对代码级的研究,并加上我个人的注释。如这篇《Swiftsuspenders浅出深入》,深如部分会详细介绍Swiftsuspenders的体系结构,每个类的实现等相关内容。这样对Swiftsuspenders可以有非常深入的了解。这样在使用Swiftsuspenders甚至优化时会有很大的帮助。这篇之后应该会跟进一篇《robotlegs浅出深入》。


    守望者AIR技术交流社区(www.airmyth.com)
    回复

    使用道具 举报

  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    52620
    钢镚
    1422

    开源英雄守望者

     楼主| 发表于 2015-1-10 21:03:00 | 显示全部楼层

    本篇《Swiftsuspenders浅出深如》的浅出部分基本上是对官方网站的教程的一个翻译和整理。原文链接:https://github.com/tschneidereit/Swiftsuspenders 。同时会在翻译的过程中添加一些我的理解和一些示例代码,以帮助读者更好的理解。

    同时Swiftsuspenders的作者Till Schneidereitblog也是一个很不错的学习Swiftsuspenders的站点,从中可以看到许多作者的开发历程和设计思路。Blog: http://www.tillschneidereit.de/

    似乎Swiftsuspenders2.0已经在开发中,会有一些API的改变和一些新的功能特性,届时会做相应的更新。


    简介

            

              Swiftsuspenders是一个基于元数据(metadata)的IOC(控制反转,inversion of control)的AS3的解决方案。(对于元数据编程,请参见《Actionscript 3 自定义 matedata》)

    它的实现类似于Josh McDonald的SmartyPants IOC [2]框架,但是略有两点不同:1. Swiftsuspenders的功能没有SmartyPants IOC那么强大; 2. Swiftsuspenders某种程度上运行的更快。

             Swiftsuspenders主要支持了很好的AS3 MVCS框架 ----Robotlegs

             为了能够在不支持自定义元数据(metadata)的Flash Professional IDE中使用Swiftsuspenders, 可以通过使用一个简单的XML配置文件的形式来配置注入点(Injection Points)


    特性

             Swiftsuspenders支持以下特性,详细内容在后续文档中会一一介绍

    • 基于元数据(metadata)标注的注入点(injection points)
    • 针对Flash Professional(CS4版本不支持自定义元数据)而设计的基于XML标注的注入点
    • 注入:

              属性(setter)

              变量

              方法(支持可选参数)

            构造函数(支持可选参数)

    • 注入名,从而可以不仅仅通过类型,而是可以允许跟多制定的注入绑定(参见定义注入点”)
    • [PostConstruct]标签申明了注入结束后需要调用的方法
    • 映射

             

              (针对每一次注入都会创建新的实例)

              单例(第一次注入创建,然后每次注入时都复用第一次创建的对象)

              规则(允许在多个映射规则之间共享单例)

    • 创建子注入器(injector),从而继承父注入器的映射关系,同时可以定义额外的映射关系或者重写父注入器的映射关系
    • 通过InjectorhasMapping方法来查询已有的注入规则
    • 通过使用InjectorgetInstance方法直接应用注入规则

    安装

             最简单的使用Swiftsuspenders的方法就是将提供的SWC库文件添加到你的项目中。如果你需要使用源代码,你必须在MXMLC设置中添加以下语句,如图所示:(注意是+= 而不是=)


    1. -keep-as3-metadata+=Inject
    2. -keep-as3-metadata+=PostConstruct
    复制代码



       

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    守望者AIR技术交流社区(www.airmyth.com)
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    52620
    钢镚
    1422

    开源英雄守望者

     楼主| 发表于 2015-1-10 21:07:29 | 显示全部楼层
    使用定义依赖(dependence)

             Swiftsuspenders支持3种依赖定义:

    • 值绑定,将一个注入请求返回为一个给定的对象
    • 类绑定,将一个注入请求返回为一个给定类的新建的实例
    • 单例绑定,将所有的注入请求返回为同一个共享的实例,这个实例由第一次请求时创建。

             另外,也可以才通过使用mapRule来重用依赖映射

             针对所有定义类型,可以使用指定的注入名来实现同一个类的多种注入绑定。

    定义注入点(Injection points)

             可以通过使用对象的构造函数,setter方法,属性或者方法(或者以上几种方法的组合)将一个依赖注入进对象。Setter方法,属性和方法注入需要在注入的类中添加元数据进行申明。当你是用构造函数注入时,你是需要添加以下元数据:

    1. [Inject]
    复制代码
    如下例:
    1. package
    2. {
    3.     public class InjecteeClass//接收注入的类
    4.     {
    5.         [Inject]public var injectPoint:InjectObject;//注入点
    6.         public function InjecteeClass()
    7.         {
    8.         }
    9.     }
    10. }

    11. package
    12. {
    13.     public class InjectObject//被注入的对象
    14.     {
    15.         public function InjectObject()
    16.         {
    17.             trace("created");//构造函数
    18.         }
    19.         public function call():void{//一个简单的方法调用
    20.             trace("called");
    21.         }
    22.     }
    23. }

    24. package
    25. {
    26.     import flash.display.Sprite;
    27.    
    28.     import org.swiftsuspenders.Injector;
    29.    
    30.     public class SwiftSuspenderDemo extends Sprite
    31.     {
    32.         public function SwiftSuspenderDemo()//一个demo
    33.         {
    34.             var injector:Injector = new Injector();//申明注入器
    35.             injector.mapClass(InjectObject,InjectObject);//对InjectorObject类进行类映射
    36.             injector.mapClass(InjecteeClass,InjecteeClass);//对InjecteeClass进行类映射
    37.             var instance:InjecteeClass = injector.getInstance(InjecteeClass);//通过注入器获取InjecteeClass对象,注入器自动完成注入
    38.             instance.injectPoint.call();//对注入过的对象进行调用
    39.         }
    40.     }
    41. }
    复制代码
    执行程序输出
    created
    called
    上面的例子中InjecteeClass是接收注入的类,内含一个注入点。 InjectObject是被注入的对象,内含一个简单的call方法。
    使用SwiftSuspenders很简单,首先创建一个Injector对象。然后在Injector中配置相应的映射。最后调用Injector对象的getInstance方法获得请求类的实例。Injector会自动完成依赖注入。上面的例子基本就是使用SwiftSuspenders的大致流程。
    如果需要申明注入名,语法如下:

    1. [Inject(name=”NamedDependency”)]
    复制代码
    如下例:
    1. package
    2. {
    3.     public class InjecteeClass//接收注入的类
    4.     {
    5.         [Inject(name="myinject")]public var injectPoint:InjectObject;//注入点,包含注入名
    6.         public function InjecteeClass()
    7.         {
    8.         }
    9.     }
    10. }


    11. package
    12. {
    13.     public class InjectObject//被注入的对象
    14.     {
    15.         private var id:String;
    16.         public function InjectObject(id:String)
    17.         {
    18.             trace("created");//构造函数
    19.             this.id = id;
    20.         }
    21.         public function call():void{//一个简单的方法调用
    22.             trace(id,"called");
    23.         }
    24.     }
    25. }

    26. package
    27. {
    28.     import flash.display.Sprite;
    29.    
    30.     import org.swiftsuspenders.Injector;
    31.    
    32.     public class SwiftSuspenderDemo extends Sprite
    33.     {
    34.         public function SwiftSuspenderDemo()//一个demo
    35.         {
    36.             var injector:Injector = new Injector();//申明注入器
    37.             var injectObj1:InjectObject = new InjectObject("id_1");//新建一个叫id_1的注入对象
    38.             var injectObj2:InjectObject = new InjectObject("id_2");//新建一个叫id_1的注入对象
    39.             injector.mapValue(InjectObject,injectObj1);//配置注入对象的映射,id_1对象不含注入名
    40.             injector.mapValue(InjectObject,injectObj2,"myinject");//id_2对象包含注入名
    41.             injector.mapClass(InjecteeClass,InjecteeClass);
    42.            
    43.             var instance:InjecteeClass = injector.getInstance(InjecteeClass);
    44.             instance.injectPoint.call();//调用注入对象的call()方法
    45.            
    46.         }
    47.     }
    48. }
    复制代码
    最后输出
    created
    created
    id 2_called
    说明InjectObj2对象被注入进了InjecteeClass对象。
             当对构造函数注入使用注入名时,元数据必须放在类定义的前面,而不是在构造函数前,这个是由于Flash Player的限制造成的。
             当方法和构造函数接收多个参数时,可以混合定义有注入名和没有注入名的依赖绑定。在这种情况下,只要将没有注入名的依赖的name属性设为空字符串就可以了,如:

    1. [Inject(name=””,name=”NamedDependency”)]
    复制代码
    如下例:
    1. package
    2. {
    3.     public class MethodInInjecteeClass
    4.     {
    5.         public var obj1:InjectObject;//需要注入的第一个对象
    6.         public var obj2:InjectObject;//需要注入的第二个对象
    7.         public function MethodInInjecteeClass()
    8.         {
    9.         }
    10.         [Inject(name="",name="myinject")]//第一个参数无注入名,第二个参数有myinject注入名
    11.         public function inject(arg1:InjectObject,arg2:InjectObject):void{//方法注入
    12.             this.obj1 = arg1;
    13.             this.obj2 = arg2;
    14.         }
    15.     }
    16. }

    17. package
    18. {
    19.     public class InjectObject//被注入的对象
    20.     {
    21.         private var id:String;
    22.         public function InjectObject(id:String)
    23.         {
    24.             trace("created");//构造函数
    25.             this.id = id;//传入一个参数
    26.         }
    27.         public function call():void{//一个简单的方法调用
    28.             trace(id,"called");//call时会返回构造时返回的参数
    29.         }
    30.     }
    31. }

    32. package
    33. {
    34.     import flash.display.Sprite;
    35.    
    36.     import org.swiftsuspenders.Injector;
    37.    
    38.     public class SwiftSuspenderDemo extends Sprite
    39.     {
    40.         public function SwiftSuspenderDemo()//一个demo
    41.         {
    42.             var injector:Injector = new Injector();//申明注入器
    43.             var injectObj1:InjectObject = new InjectObject("id_1");//新建一个叫id_1的注入对象
    44.             var injectObj2:InjectObject = new InjectObject("id_2");//新建一个叫id_1的注入对象
    45.             injector.mapValue(InjectObject,injectObj1);//配置注入对象的映射,id_1对象不含注入名
    46.             injector.mapValue(InjectObject,injectObj2,"myinject");//id_2对象包含注入名
    47.             injector.mapClass(MethodInInjecteeClass,MethodInInjecteeClass);
    48.            
    49.             var instance:MethodInInjecteeClass = injector.getInstance(MethodInInjecteeClass);
    50.             instance.obj1.call();//分别调用两个注入对象的call方法
    51.             instance.obj2.call();
    52.            
    53.         }
    54.     }
    55. }
    复制代码
    最后输出:
    created
    created
    id_1 called
    id_2 called
    对于方法和构造函数,只有必填参数需要有注入映射,可选参数如果定义了依赖则使用注入,没有就使用默认值。
             在继承的类中,注入点同样会像定义的那样工作。因此,可以为父类定义注入点,然后所有的子类都会继承。
             构造函数注入的问题:以下是对构造函数注入的一些警告。由于Flash player的一个bug。一个类的完整的构造函数参数的信息只有在该类被至少实例化过一次后才能获得。要解决这个bug带来的问题,Swiftsuspenders在应用构造函数注入之前,会检查构造函数的参数信息是否可用。如果不可用,Swiftsuspenders会创创建一个抛出异常的该类的实例。由于这个行为,在使用构造函数注入的类中,构造函数不要有任何复杂的逻辑。

    守望者AIR技术交流社区(www.airmyth.com)
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    52620
    钢镚
    1422

    开源英雄守望者

     楼主| 发表于 2015-1-10 21:23:03 | 显示全部楼层
    PostConstruct:注入完成后自动调用方法

             基于自动的依赖注入的类的实例只有在依赖注入完成以后才可以被使用。为了在被注入的类中安全的使用实例,可以申明[PostConstruct]元数据,从而在所有的注入完成后,自动调用被[PostConstruct]申明的方法。可以通过order参数来决定方法调用的顺序,如:


    1. [PostConstruct(order=1)]
    复制代码
    如下例
    1. package
    2. {
    3.     public class InjecteeClass//接收注入的类
    4.     {
    5.         [Inject]public var injectPoint:InjectObject;//注入点
    6.         public function InjecteeClass()
    7.         {
    8.         }
    9.         [PostConstruct(order=1)]
    10.         public function order1():void{//定义注入完成后执行的第一个函数
    11.             trace("post 1");
    12.         }
    13.       
    14.         [PostConstruct(order=2)]
    15.         public function order2():void{//定义注入完成后执行的第一个函数
    16.             trace("post 2")
    17.         }
    18.     }
    19. }

    20. package
    21. {
    22.     public class InjectObject//被注入的对象
    23.     {
    24.         public function InjectObject()
    25.         {
    26.             trace("created");//构造函数
    27.         }
    28.         public function call():void{//一个简单的方法调用
    29.             trace("called");
    30.         }
    31.     }
    32. }

    33. package
    34. {
    35.     import flash.display.Sprite;
    36.    
    37.     import org.swiftsuspenders.Injector;
    38.    
    39.     public class SwiftSuspenderDemo extends Sprite
    40.     {
    41.         public function SwiftSuspenderDemo()//一个demo
    42.         {
    43.            
    44.             var injector:Injector = new Injector();//申明注入器
    45.             injector.mapClass(InjectObject,InjectObject);//对InjectorObject类进行类映射
    46.             injector.mapClass(InjecteeClass,InjecteeClass);//对InjecteeClass进行类映射
    47.                   
    48.                        
    49.             var instance:InjecteeClass = injector.getInstance(InjecteeClass);//通过注入器获取InjecteeClass对象,注入器自动完成注入
    50.             instance.injectPoint.call();//对注入过的对象进行调用
    51.            
    52.         }
    53.     }
    54. }
    复制代码

    输出结果:

    created
    post 1
    post 2

    called

        可以看出,在完成注入后,分别调用了order1和order2方法。通过PostConstruct元数据可以完成注入后的一些逻辑代码。

    查询注入映射

             1.5版本以后,Swiftsuspenders可以通过Injector类的hasMapping方法查询已有映射规则的存在性,hasMapping方法会通过类或接口的加上注入名来查询是否有相应的注入映射。如果有返回ture,没有则返回false

    直接应用注入

             SwiftSuspenders1.5以后,可以通过使用InjectorgetInstance方法直接应用注入。getInstance方法需要传入一个类或者接口(注入名可选),从而返回开发者定义的映射结果。如果没有定义,则会抛出异常

             返回的值依赖于定义的请求映射。如,已经为一个请求定义了一个单例映射,则共享的单例对象在接受请求时会被返回,而不是新建一个实例。

    异常处理

             如果请求的注入映射没有找到,包含目标类和请求属性类型的异常会被抛出。

    子注入器(Injector)

             SwiftSuspenders1.5开始,支持创建子注入器(Injector)。子注入器会依赖父注入器,并且会自动继承父注入器的映射规则。除此之外,资注入器还可以有自己的隐射规则,同时还可以重写父注入器的映射规则。

             这个特性主要为解决所谓的机器人腿问题”(robot legs problem)。当使用依赖注入时,开发者希望创建只有很轻微差别的相思的对象树。以一个简单的机器人(robot)为例,这个机器人可以使用相同的零件做腿(leg),但是需要使用不同的零件分辨做为左脚(left foot)和右脚(right foot)。使用传统的依赖注入,开发者需要针对RobotLeg类分别扩展子类,从而实现对不同脚的不同注入,子类会实现样板代码来父类希望注入的脚的对象。如下例

    1. public class Robot//机器人类
    2. {
    3.          [Inject] public var leftLeg : LeftRobotLeg;//属性注入,左腿
    4.          [Inject] public var rightLeg : RightRobotLeg;//属性注入,右腿
    5. }

    6. public class RobotLeg//腿的父类
    7. {
    8.          protected var foot : RobotFoot;//脚属性
    9. }

    10. public class LeftRobotLeg extends RobotLeg//左腿类
    11. {
    12.          [Inject] public function set foot (foot : LeftRobotFoot) : void//方法注入,注入一个左脚
    13.          {
    14.                    this.foot = foot;
    15.          }
    16. }

    17. public class RightRobotLeg extends RobotLeg//右腿类
    18. {
    19.          [Inject] public function set foot (foot : RightRobotFoot) : void//方法注入,注入一个右脚
    20.          {
    21.                    this.foot = foot;
    22.          }
    23. }

    24. public class RobotConstruction
    25. {
    26.          var injector : Injector = new Injector();//申明一个注入器
    27.          injector.mapClass(LeftRobotLeg, LeftRobotLeg);//左腿类映射
    28.          injector.mapClass(RightRobotLeg, RightRobotLeg);//右腿类映射
    29.          injector.mapClass(LeftRobotFoot, LeftRobotFoot);//左脚类映射
    30.          injector.mapClass(RightRobotFoot, RightRobotFoot);//右脚类映射
    31.          var robot : Robot = injector.instantiate(Robot);//实例化机器人,自动完成所有注入
    32. }
    复制代码
      而使用子注入器,机器人可以值使用RobotLeg类进行构建,并且同时支持对不同的腿注入不同的脚,如:
    1. public class Robot//机器人类
    2. {
    3.          [Inject(name=‘leftLeg’)] public var leftLeg : RobotLeg;//属性注入,注入名为左腿
    4.          [Inject(name=‘rightLeg’)] public var rightLeg : RobotLeg;//属性注入,注入名为右腿
    5. }

    6. public class RobotLeg//腿类
    7. {
    8.          protected var foot : RobotFoot;
    9. }

    10. public class RobotConstruction
    11. {
    12.          var injector : Injector = new Injector();//申明注入器
    13.          var leftLegRule : InjectionConfig = injector.mapClass(RobotLeg, RobotLeg, ‘leftLeg’); //定义左腿注入配置(InjectionConfig)
    14.          var leftLegInjector : Injector = injector.createChildInjector(); //创建左腿子注入器
    15.          leftLegInjector.mapClass(RobotFoot, LeftRobotFoot); //左腿子注入器加入左脚映射
    16.          leftLegRule.setInjector(leftLegInjector); //为左腿注入规则定义相应的注入器, 这里其实是SwiftSuspenders实现决定的,如果一个注入配置没有设置特有的注入器(Injector),那么会调用创建该注入规则的注入器进行注入;如果诸如配置设置了特有的注入器,那么优先调用设置的注入器进行注入,这部分会在深入部分的源码分析中详细阐述。

    17.                //以下为右腿,与左腿类似
    18.          var rightLegInjector : Injector = injector.createChildInjector();
    19.          rightLegInjector.mapClass(RobotFoot, RightRobotFoot);
    20.          rightLegRule.setInjector(rightLegInjector);
    21.          //finally, create the object tree by instantiating the Robot class:
    22.          var robot : Robot = injector.instantiate(Robot);//创建实例,所有注入自动完成
    23. }
    复制代码

      子注入器会将它们没有的映射请求推送到它们的父注入器。这样就可以在注入器之间共享额外的映射规则。例如,机器人的脚可能会有脚指头对象,这些脚指头对不同的脚都是相同的,所以针对脚指头的映射就会添加到父亲注入器而不是每一个子注入器中。

             如果一个从父注入器的映射被使用了,这不代表子注入器不再被随后的注入使用了。例如,你可以在你的子注入器中有一个洞,这个洞会由祖先注入器来弥补,然后任然在你的子注入器中定义其他的,你想要在以后通过依赖注入构建对象树时使用的隐射。

             注入器可以创建任意复杂度的配置树。

    基于XML配置注入点(Injection points)

             注意:现在已经可以再Flash CS3/4/5中使用元数据了。所以基于XML配置注入点的主要原因就不复存在了。为了让你的应用支持所有的元数据,请检查在发布设置(Publish Settings)面板中的导出SWC文件(export swc)选项。更多的信息请参考博客:http://www.patrickmowrer.com/2010/03/03/compiling-custom-as3-metadata-flash-professional

             Injector类的构造函数中有一个可选的参数,这个参数是一个XML对象,如果这个XML被提供了,SwiftSuspenders就会根据这个XML来配置所有的注入点

             XML配置文件由一系列的<type />节点组成,这些节点代表了注入点。注入的目标类由name属性指定。Setter注入和属性注入有<field />节点指定,方法注入由<method />节点指定,构造函数注入由<constructor />节点指定。对于所有的注入类型,目标属性由name属性给出,要指定注入的注入名,可以通过injectionname属性指定。对于方法和构造函数注入,多个参数可以由<arg />节点定义。

             注入类型仍然由运行时的反射机制获得,所以不需要对注入类型进行支持。

             除了注入点之外,PostConstruct方法同样可以通过添加<postconstruct />节点声明

             下面的示例代码包含了所有可能的配置选项

    1. <types xmlns="http://github.com/tschneidereit/SwiftSuspenders">
    2.          <type name='com.example.injectees::FirstInjectee'>
    3.                    <field name='unnamedInjectionPoint'/>
    4.                    <field name='namedInjectionPoint' injectionname='namedInjection'/>
    5.                    <postconstruct name='firstPostConstructMethod' order='1'/>
    6.                    <postconstruct name='secondPostConstructMethod' order='2'/>
    7.          </type>
    8.          <type name='com.example.injectees::SecondInjectee'>
    9.                    <method name='unnamedInjectionMethod'/>
    10.                    <method name='namedInjectionMethodWithOneArgument' injectionname='namedInjection'/>
    11.                   <method name='namedInjectionMethodWithMultipleArguments'>
    12.                             <arg injectionname='namedInjection'/>
    13.                             <arg injectionname='namedInjection2'/>
    14.                    </method>
    15.          </type>
    16.          <type name='com.example.injectees::ThirdInjectee'>
    17.                    <constructor>
    18.                             <arg injectionname='namedInjection'/>
    19.                             <arg injectionname='namedInjection2'/>
    20.                    </constructor>
    21.          </type>
    22. </types>
    复制代码

    注意,要确保Flash IDE MXMLC(如,flex)编译的一样,如果XML配置文件使用时,SwiftSuspenders会忽略所有的元数据。

             swiftSuspenders是一个基于元数据的依赖注入框架,元数据是AS3的特有一种特性。其时本质上AS3的元数据就是在AS类的XML表示中添加一些自定义的标签。所以本质上,swiftsuspenders还是一个基于XML进行依赖注入配置的框架。基于XML的配置实际上相当于手动添加元数据信息。

             依赖注入是针对对象的进一步解耦,将对象之间的耦合关系通过一种配置文件进行表示(通常是XML),然后通过解析配置文件将对象之间的依赖关系进行注入,从而生成对象。

             使用外部XML的另一个好处是可以动态载入,基于元数据的注入如果需要修改,需要重新编译源码,这也有一些违背依赖注入设计的一些初衷。而通过外部的XML进行依赖配置,可以动态的更改依赖而不需要重新编译代码。所以基于XML的依赖配置还是很有作用的。

    范例(官方提供)属性和setter注入

             假设你的类需要注入依赖如下:

    1. package
    2. {
    3.          public class MyDependentClass//需要注入的类
    4.          {
    5.                    [Inject]
    6.                    public var firstDepency : MovieClip;//申明一个MovieClip类型的注入点,无注入名
    7.                   
    8.                    [Inject(name="currentTime")]
    9.                    public var secondDependency : Date;//申明一个Date类型的注入点,注入名为currentTime
    10.                   
    11.                    [Inject]
    12.                    public function set thirdDependency(value : Sprite) : void//申明一个setter方法的注入点,无注入名
    13.                    {
    14.                             m_thirdDependency = value;
    15.                    }
    16.                    private var m_thirdDependency : Sprite;
    17.          }
    18. }
    复制代码
    要想向这个对象的实例里面进行依赖注入,你需要首先定义依赖映射,然后调用Injector的InjectInto方法,如下:
    1. var injector : Injector = new Injector();
    2. injector.mapValue(MovieClip, new MovieClip());//值映射
    3. var currentTime : Date = new Date();
    4. injector.mapValue(Date, currentTime, 'currentTime');//带有注入名的值映射
    5. injector.mapSingleton(Sprite); //单例映射
    6. var injectee : MyDependentClass = new MyDependentClass();
    7. injector.injectInto(injectee);//注入依赖
    复制代码
    方法注入

             假设你的类需要注入依赖如下:

    1. package
    2. {
    3.          public class MyDependentClass
    4.          {
    5.                    private var myMovieClip : MovieClip;
    6.                    private var currentTime : Date;
    7.                   
    8.                    [Inject]
    9.                    public function setFirstDependency(injection : MovieClip) : void//方法注入,不带注入名
    10.                    {
    11.                             myMovieClip = injection;
    12.                    }
    13.                   
    14.                    [Inject(name="currentTime")]//方法注入,带有名为currentTime的注入名,单个参数
    15.                    public function setSecondDependency(injection : Date) : void
    16.                    {
    17.                             currentTime = injection;
    18.                    }
    19.                   
    20.                    [Inject(name='', name="currentTime")]//方法注入,带有名为currentTime的注入名,多个参数
    21.                    public function setMultipleDependencies(movieClip : MovieClip, date : Date) : void
    22.                    {
    23.                             myMovieClip = movieClip;
    24.                             currentTime = date;
    25.                    }
    26.          }
    27. }
    复制代码
    -要想向这个对象的实例里面进行依赖注入,你需要首先定义依赖映射,然后调用Injector的InjectInto方法,如下:
    1. var injector : Injector = new Injector();
    2. injector.mapValue(MovieClip, new MovieClip());
    3. var currentTime : Date = new Date();
    4. injector.mapValue(Date, currentTime, 'currentTime');
    5. var injectee : MyDependentClass = new MyDependentClass();
    6. injector.injectInto(injectee);
    复制代码
    构造函数注入

             假设你的类需要注入依赖如下:

    1. package
    2. {
    3.          [Inject(name='', name="currentTime")]
    4.          public class MyDependentClass//构造函数注入需要写在类之前
    5.          {
    6.                    private var myMovieClip : MovieClip;
    7.                    private var currentTime : Date;
    8.                   
    9.                    public function MyDependentClass(movieClip : MovieClip, date : Date)
    10.                    {
    11.                             myMovieClip = movieClip;
    12.                             currentTime = date;
    13.                    }
    14.          }
    15. }
    复制代码
    要想向这个对象的实例里面进行依赖注入,你需要首先定义依赖映射,然后调用Injector的InjectInto方法,如下:
    1. var injector : Injector = new Injector();
    2. injector.mapValue(MovieClip, new MovieClip());
    3. var currentTime : Date = new Date();
    4. injector.mapValue(Date, currentTime, 'currentTime');
    5. var injectee : MyDependentClass = injector.instantiate(MyDependentClass);
    复制代码
    至此SwiftSuspenders 1.6 浅出深入的浅出部分就结束了,相信通过这篇浅出教程大家应该可以对SwiftSuspenders 有个大致的认识。之前没有过依赖注入编程经验的童鞋应该会对依赖注入有一个大致的认识。之前有过依赖注入相关知识了解的童鞋应该已经可以采用SwiftSuspenders做相应的开发了。
    后面开始就会进入SwiftSuspenders 1.6 浅出深入 的深入部分。

    传送门:

    守望者AIR技术交流社区(www.airmyth.com)
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    
    关闭

    站长推荐上一条 /4 下一条

    QQ|手机版|Archiver|网站地图|小黑屋|守望者 ( 京ICP备14061876号

    GMT+8, 2024-3-29 13:39 , Processed in 0.055426 second(s), 31 queries .

    守望者AIR

    守望者AIR技术交流社区

    本站成立于 2014年12月31日

    快速回复 返回顶部 返回列表