守望者--AIR技术交流

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

搜索
热搜: ANE FlasCC 炼金术
查看: 2380|回复: 7
打印 上一主题 下一主题

[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
    金币
    52692
    钢镚
    1422

    开源英雄守望者

    跳转到指定楼层
    楼主
    发表于 2015-1-10 21:22:02 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    本系列文章来自:http://sswilliam.blog.163.com/blog/static/189696383201175114948372/


    接上篇:SwiftSuspenders 1.6 浅出深入 浅出


    深入

             这篇SwiftSuspenders 浅出深入的 深入部分主要是对SwiftSuspenders进行深度剖析,包括对SwiftSuspenders的体系结构的分析,一个对象在整个注入过程中会经历怎样的生命周期,以及对SwiftSuspenders每个类的详细解读。

    术语表

    首先为了表达的明确性,先列下了一些可能在文章中用到的术语。这样便于减少理解上的歧义:

    为了解释清楚术语之间的关系,我们设计以下场景以进行类比:闪闪同学生病了,需要进行打针治疗。

    术语名
    英文
    解释
    依赖
    Dependency
    面向对象中类之间的关系,简单来说,当A类的某些功能需要B类进行辅助时,就说A类对B类有依赖。如闪闪同学需要药来治病,那么就说闪闪对药有依赖
    注入
    Injection
    一种建立依赖关系的行为。如闪闪同学要使用药,就必须让药进入体内(引用关系)。如何让药进入体内呢?需要一个针筒,通过注射来获得药物。这就是注入。当AB的依赖关系由C来建立。BC注入进了A
    注入器
    Injector
    就是SwiftSuspenders里面的Injector类的一个实例,相当于扮演针筒的角色。
    注入配置
    InjectionConfig
    是针对一个注入行为的配置对象。包含注入请求的类和注入名。所使用的注入器和返回结果的策略等信息。如闪闪得的是感冒,需要注射感冒药,还需要注射消炎药,这时候闪闪就要请求两种类型的药。同一种类型的药,可能还有不同的品牌,所以有的时候还需要加上请求的药的名字,就相当于注入名。注入配置就相当于一张处方单。
    注入点
    InjectionPoint
    依赖注入分几种形式,如,构造函数注入,属性注入和方法注入。这些都称做注入点。比如打针,可以打PP,也可以打胳膊。属性注入就是对public的属性或者有setter方法进行复制,方法注入就是像某个函数传参。
    注入描述
    InjecteeDescription
    包含了一个被注入对象的所有的注入点。比如闪闪打针,需要在胳膊打一针,需要在屁股打两针。就会描述在注入描述里面。InjecteeDescriptionInjector的一个包外类。
    返回策略
    InjectionResult
    反应了注入器以何种方式对请求进行注入,如直接新建一个B对象,然后注入A,或者以单例模式新建一个B对象,然后所有使用B的注入都会共享同一个对象等等。

    体系结构

    SwiftSuspenders的类图如上图所示。整个框架以Injector为核心。InjectionPoint包中包含了所有与注入点相关的类,InjectionResult包中包含了返回策略相关的类。其他的类都是配合Injector类进行工作。具体的类的解读会在下一章进行深入介绍。
    其中用到的设计模式主要有策略模式,模板方法。
    在InjectionResult包中主要使用了通过策略模式,作者针对不同的需求创造了不同的映射策略,如单例模式,类模式,对象模式。同时还允许开发者开发其他所需的策略。
    在InjectionPoint包中主要使用了模板方法,通过让不同的子类实现initializeInjection这个钩子(hook)方法从而实现不同的注入点
    对象生命周期
             这一章主要从内部分析SwiftSuspender的两个主要活动:映射和注入的流程
    映射顺序图
    以mapClass为例,首先主程序调用Injector的mapClass方法,传入所需的参数;
    然后Injector调用自身的getMapping方法,获得一个相应的注入配置对象,如果再此之前已经建立过相应的注入配置,则直接返回,如果没有,就会新建一个注入配置对象
    获得注入配置对象后,就会调用得到的InjectionConfig的setResult方法设置该配置的返回策略。如为类映射是,就设置为InjectClassResult。如果是单例,则设置为InjectSingletonResult。以此类推。
    最后返回设置好各项参数的InjectionConfig。同时该InjectionConfig对象就会存在Injector的m_mappings的Dictionary中。整个映射的过程就完成了。
    注入顺序图
    通过Injector的getInstance()方法可以获得注入后的对象。主程序通过向Injector发送类+注入名的请求以获得对象。
    Injector得到请求后,调用自身的getConfigurationForRequest()方法获得相应的InjectionConfig注入配置.
    获得注入配置后,调用InjectionConfig的getResponse()方法获得结果。
    InjectionConfig的getResponse()方法会调用相应的InjectionResult返回策略的getResponse()方法获得结果。如果traverseAncestors设为true,那么当在当前的注入器中没有找到相应的注入配置时,还会从下至上依次遍历其祖先注入器,直到找到位置。
    InjectionResult会调用Injector的instantiate()方法获得对象。
    在Injector的instantiate方法会调用Injector的getInjectionPoints方法获得需要注入的类的所有的注入点。然后调用构造函数注入点先获得所请求类的实例。
    在得到请求类的实例后,Injector会调用自身的InjectInto方法像这个对象的其他注入点进行依赖注入。
    最后将注入完成的结果返回给程序。在注入的过程中,如果遇到被注入的对象仍然需要依赖注入,就会和上面的流程一样,对被注入的对象同样执行依赖注入,然后再将注入完的对象注入进目标对象。



    本帖子中包含更多资源

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

    x
    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
    收藏收藏 分享分享 支持支持 反对反对 微信
    守望者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
    金币
    52692
    钢镚
    1422

    开源英雄守望者

    沙发
     楼主| 发表于 2015-1-10 21:24:17 | 只看该作者
    类解读Injector

             Injector是整个SwiftSuspenders框架的核心。与开发者打交道最多的也就是Injector类。Injector就是注入器,其功能相当于Spring里的ApplicationContext。是IOC容器。简单的理解可以将它理解为一个工厂,当开发者需要一个对象的时候,不是new出这个对象,而是通过Injector得到这个对象。Injector会自动完成返回的对象的依赖注入。

             Injector的私有属性如下

    属性名
    功能
    INJECTION_POINTS_CACHE[static]:Dictionary
    一个静态属性,缓存所有注入器的注入点描述。如果一个注入器通过xml来配置注入点,则不会和其他注入器共享注入点的缓存;如果不是通过xml来配置注入点,则会所有的注入器都共享注入点缓存,这也是基于性能的考虑。由于分析一个类的注入点需要通过describeType方法解析类的XML描述,如果两个注入器会映射相同的类,那么只需要解析一遍就可以了。注意:这个变量缓存的是类的注入点(InjectionPoints)信息而非注入配置(InjectionConfig)。注入器之间是不共享注入配置信息的。如A1注入器已经映射过一次B类,如果A2注入器再映射B类时,就直接使用A1注入器映射过的B类的注入点信息而不需要自己再一次运算了。因为同一个类的注入点一定是相同的。
    m_parentInjector : Injector
    父注入器的引用
    m_applicationDomain:
    ApplicationDomain
    注入器工作的应用程序域
    m_mappings: Dictionary
    存储所有该注的注入配置(InjectionConfig)
    m_injecteeDescriptions: Dictionary
    存储该注入器相关的的注入点描述。如果不是通过xml进行注入点配置的话,该属性指向INJECTION_POINTS_CACHE,即所有的注入器共享类的注入点信息
    m_attendedToInjectees: Dictionary
    存储已经注入过的对象。这样在下一次请求时,就不需要再执行注入操作。以提升性能。
    m_xmlMetadataXML
    配置注入信息的XML文件。

             Injector公有方法如下

    方法名
    功能
    Injector(xmlConfig : XML = null)
    构造函数,初始化注入器的一些私有变量,如果是通过xml进行配置。就在参数里面写入。这样注入器就会设置为xml配置的模式。
    mapValue(whenAskedFor : Class, useValue : Object, named : String = "") : *
    值映射。将一个请求[类的全名+#+注入名映射为一个已有的对象
    mapClass(whenAskedFor : Class, instantiateClass : Class, named : String = "") : *
    类映射,将一个请求[类的全名+#+注入名映射为一个类。注意,被映射的类和请求的类可以毫无关系。
    mapSingleton(
    whenAskedFor : Class, named : String = "") : *
    单例映射,将一个请求[类的全名+#+注入名映射为该类的单例对象。
    mapSingletonOf(
    whenAskedFor : Class, useSingletonOf : Class, named : String = "") : *
    单例类映射,将一个请求[类的全名+#+注入名映射为另一个类的单例对象。注意,被映射的类和请求的类可以毫无关系。
    mapRule(whenAskedFor : Class, useRule : *, named : String = "") : *
    规则映射。将一个请求[类的全名+#+注入名映射另一个注入配置的返回策略(个人觉得这个方法其实没什么作用。还不如将第二个参数设为自定义的InjectionResult。这样还可以增加可扩展性)
    getMapping
    (whenAskedFor : Class, named : String = "")
    根据请求获得相应的注入配置。如果已有相应的注入配置,直接从mappings缓存里面返回,如果没有,则会新建一个相应的注入配置。然后保存在mapping中。
    injectInto(target : Object):void
    向目标对象进行依赖注入。(只包括属性注入和方法注入)。构造函数注入在生成目标对象时就已经完成了。
    instantiate(clazz:Class):*
    实例化一个类。会通过构造函数注入方法新建这个类,然后调用injectInto方法完成这个对象的依赖注入。最后返回完成注入的对象。
    unmap(clazz : Class, named : String = ""):*
    解除一个映射。内部只是将该映射的InjectionConfig的返回策略设为空。(个人认为应该还需要将mapping里面的引用删掉)
    hasMapping(clazz : Class, named : String = '') : Boolean
    根据一个请求检测是否存在相应的注入配置(InjectionConfig)
    getInstance(clazz : Class, named : String = '') : *
    根据请求返回相应的实例。该实例已经完成所有的依赖注入。
    createChildInjector(applicationDomain:ApplicationDomain=null) : Injector
    创建子注入器
    setApplicationDomain(applicationDomain:ApplicationDomain):void
    设置注入器的应用程序域
    getApplicationDomain():ApplicationDomain
    获得注入器的应用程序域
    setParentInjector(parentInjector : Injector)
    设置注入器的父注入器
    getParentInjector() : Injector
    获得注入器的父注入器
    purgeInjectionPointsCache()
    清除注入点缓存。

             Injector包内方法如下:

    方法名
    功能
    getAncestorMapping(
    whenAskedFor : Class, named : String = null) : InjectionConfig
    自下而上依次从父注入器获得请求的注入配置。直到找到为止。注意:只会寻找离当前注入器最近的注入配置。如A的父注入器是BB的父注入器是CBC有相同请求名的注入配置。那么A只会使用B的注入配置。
    get attendedToInjectees() : Dictionary
    获得所有已经住如过的对象。

             Injector的私有方法如下:

    方法名
    功能
    getInjectionPoints(clazz : Class) : InjecteeDescription
    获得一个类的注入描述(InjecteeDescription)。这个注入描述中包含了这个类所有的注入点信息。通过describeType方法获得这个类的XML表示。然后查找包含Inject元数据和PostConstruct元数据的节点来配置相应的注入点。最后封装到InjecteeDescription对象中
    getConfigurationForRequest(clazz : Class, named : String, traverseAncestors : Boolean = true) : InjectionConfig
    根据请求返回相应的注入配置(InjectionConfig)。traverseAncestors决定是会从父注入器中查找。
    createInjectionPointsFromConfigXML(description : XML)
    xml中配置注入点信息。大体的流程是首先清除原来类中的所有元数据信息,然后根据配置的xml,重新添加新的元数据信息。
    addParentInjectionPoints(description : XML, injectionPoints : Array) : void
    从父类中找到注入点,然后添加进子类的注入点描述当中。因为子类也应该继承父类的注入点信息。

             Injector包外类:InjecteeDescription

    InjecteeDescription描述了一个类的注入点信息。内含两个公有属性:

    属性名
    功能
    Ctor:InjectionPoint
    构造函数注入点
    injectionPoints :Array
    属性,方法和PostConstruct注入点


    守望者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
    金币
    52692
    钢镚
    1422

    开源英雄守望者

    板凳
     楼主| 发表于 2015-1-10 21:28:46 | 只看该作者
    Injector类的完整注释如下:
    1. /*
    2. * Copyright (c) 2009-2010 the original author or authors
    3. *
    4. * Permission is hereby granted to use, modify, and distribute this file
    5. * in accordance with the terms of the license agreement accompanying it.
    6. */

    7. package org.swiftsuspenders
    8. {
    9.     import flash.system.ApplicationDomain;
    10.     import flash.utils.Dictionary;
    11.     import flash.utils.Proxy;
    12.     import flash.utils.describeType;
    13.     import flash.utils.getDefinitionByName;
    14.     import flash.utils.getQualifiedClassName;
    15.    
    16.     import org.swiftsuspenders.injectionpoints.ConstructorInjectionPoint;
    17.     import org.swiftsuspenders.injectionpoints.InjectionPoint;
    18.     import org.swiftsuspenders.injectionpoints.MethodInjectionPoint;
    19.     import org.swiftsuspenders.injectionpoints.NoParamsConstructorInjectionPoint;
    20.     import org.swiftsuspenders.injectionpoints.PostConstructInjectionPoint;
    21.     import org.swiftsuspenders.injectionpoints.PropertyInjectionPoint;
    22.     import org.swiftsuspenders.injectionresults.InjectClassResult;
    23.     import org.swiftsuspenders.injectionresults.InjectOtherRuleResult;
    24.     import org.swiftsuspenders.injectionresults.InjectSingletonResult;
    25.     import org.swiftsuspenders.injectionresults.InjectValueResult;
    26.    
    27.     /**
    28.      * Injector注入器,即IOCcontainer,相当于Spring里面的ApplicationContext
    29.      * 类似于工厂,通过注册类来获取实例,同时会添加实例的依赖
    30.      * 通过Injector获得的对象已经完成了依赖注入
    31.      */
    32.     public class Injector
    33.     {
    34.         /*******************************************************************************************
    35.         *                               private properties                                         *
    36.         *******************************************************************************************/
    37.         /**
    38.          * 注入点缓存
    39.          * 静态的缓存
    40.          * */
    41.         private static var INJECTION_POINTS_CACHE : Dictionary = new Dictionary(true);
    42.       
    43.       
    44.         /**
    45.          * 父注入器(Injector)对象
    46.          * */
    47.         private var m_parentInjector : Injector;
    48.         /**
    49.          * 注入器(Injector)对象的应用用程序域(ApplicationDomain)
    50.          * */
    51.         private var m_applicationDomain:ApplicationDomain;
    52.       
    53.         /**
    54.          * [类的全名+#+注入名]与注入配置对象(InjectorConfig)的映射
    55.          * key是[类的全名+#+注入名]
    56.          * value是InjectionConfig对象
    57.          * 用来存储该注入器(Injector)所有的注入配置(InjectorConfig)
    58.          * */
    59.         private var m_mappings : Dictionary;
    60.         /**
    61.          * 注入描述对象字典,key为[class+name],value为InjectionConfig对象
    62.          *
    63.          * */
    64.         private var m_injecteeDescriptions : Dictionary;
    65.         /**
    66.          * 已经注入过的对象映射字典
    67.          * 采用Dictionary的原因是Dictionary采用===来比较,是根据对象来比较而不是根据toString();
    68.          * 这样是将对象和对象的注入描述进行映射
    69.          *
    70.          * */
    71.         private var m_attendedToInjectees : Dictionary;
    72.         /**
    73.          * 注入描述xml,在[Inject]元数据不支持时使用
    74.          * */
    75.         private var m_xmlMetadata : XML;
    76.       
    77.       
    78.         /*******************************************************************************************
    79.         *                               public methods                                             *
    80.         *******************************************************************************************/
    81.         /**
    82.          * 构造函数
    83.          * @param xmlConfig - xml配置文件,可以通过外部xml来进行注入器(Injector)的注入的配置,弥补[Inject]无法使用情况,默认是null
    84.          * */
    85.         public function Injector(xmlConfig : XML = null)
    86.         {
    87.             m_mappings = new Dictionary();//初始化m_mappings
    88.             if (xmlConfig != null)//如果有配置文件
    89.             {
    90.                 m_injecteeDescriptions = new Dictionary(true);//m_injecteeDescriptions注入描述字典对象新建为Injector对象的动态字典对象
    91.             }
    92.             else//如果没有配置文件
    93.             {
    94.                 m_injecteeDescriptions = INJECTION_POINTS_CACHE;//m_injecteeDescriptions注入描述字典对象使用Injector的类的静态字典对象,这样多个注入器(Injector)共享同一个
    95.             }
    96.             m_attendedToInjectees = new Dictionary(true);//初始化m_attendedToInjectees对象
    97.             m_xmlMetadata = xmlConfig;//初始化xml元数据对象
    98.         }
    99.         /**
    100.          * 将类映射到一个对象,这样在请求[class+name]的时候,就会返回指定的对象
    101.          * @param whenAskedFor - 请求的类
    102.          * @param useValue - 请求类时返回的对象
    103.          * @named named - 注入名,对类进一步区分,[whenAskedFor的全名+'#'+named]是映射的key
    104.          *
    105.          * @return 返回一个结果策略为InjectValueResult的注入配置(InjectionConfig)对象
    106.          *
    107.          *
    108.          */
    109.         public function mapValue(whenAskedFor : Class, useValue : Object, named : String = "") : *
    110.         {
    111.             var config : InjectionConfig = getMapping(whenAskedFor, named);//根据[class的全名+name]从m_mappings中获取一个注入配置(InjectionConfig)对象,
    112.             //getMapping(whenAskedFor, named)方法会根据[class的全名+name]检测m_mappings中是否有相应的注入配置(InjectionConfig)对象
    113.             //如果有直接从m_mappings返回
    114.             //如果没有,则新建一个注入配置(InjectionConfig)对象,然后存储在m_mappings,然后返回
    115.             config.setResult(new InjectValueResult(useValue));//设置获得的注入配置(InjectionConfig)对象注入结果(InjectionResult)策略,此处设置的是InjectValueResult策略。
    116.             return config;//返回注入配置(InjectionConfig)对象
    117.         }
    118.       
    119.         /**
    120.          * 将A类映射到B类,这样在请求A类+name的时候,就会返回指一个B类对象的实例
    121.          * @param whenAskedFor - 请求的类
    122.          * @param instaniateClass - 返回对象的类
    123.          * @named named - 注入名,对类进一步区分,[whenAskedFor的全名+'#'+named]是映射的key
    124.          *
    125.          * @return 返回一个结果策略为InjectClassResult的注入配置(InjectionConfig)对象
    126.          */
    127.         public function mapClass(
    128.                 whenAskedFor : Class, instantiateClass : Class, named : String = "") : *
    129.         {
    130.             var config : InjectionConfig = getMapping(whenAskedFor, named);//根据[class的全名+name]从m_mappings中获取一个注入配置(InjectionConfig)对象
    131.             config.setResult(new InjectClassResult(instantiateClass));//设置获得的注入配置(InjectionConfig)对象注入结果(InjectionResult)策略,此处设置的是InjectClassResult策略。
    132.             return config;//返回注入配置(InjectionConfig)对象
    133.         }
    134.         /**
    135.          * 设置A类到A类的单例映射,这样在通过[askforclass+name]请求对象时的时候,就会返回一个A类的单例对象
    136.          * @param whenAskedFor - 请求的类
    137.          * @named named - 注入名,对类进一步区分,[whenAskedFor的全名+'#'+named]是映射的key
    138.          *
    139.          * @return 返回一个结果策略为InjectSingletonResult的注入配置(InjectionConfig)对象
    140.          */
    141.         public function mapSingleton(whenAskedFor : Class, named : String = "") : *
    142.         {
    143.             return mapSingletonOf(whenAskedFor, whenAskedFor, named);//调用mapSingletonOf方法,mapSingletonOf可以设置A类到B类的单例映射
    144.             //即请求[A类的全名+name]时,返回的是B类的单例对象
    145.         }
    146.         /**
    147.          * 设置A类到B类的单间映射,这样在通过[askforclass+name]请求对象时的时候,就会返回一个B类的单例对象
    148.          * @param whenAskedFor - 请求的类
    149.          * @param useSingletonOf - 返回对象的类
    150.          * @named named - 注入名,对类进一步区分,[whenAskedFor的全名+'#'+named]是映射的key
    151.          *
    152.          * @return 返回一个结果策略为InjectSingletonResult的注入配置(InjectionConfig)对象
    153.          */
    154.         public function mapSingletonOf(
    155.             whenAskedFor : Class, useSingletonOf : Class, named : String = "") : *
    156.         {
    157.             var config : InjectionConfig = getMapping(whenAskedFor, named);//根据[class的全名+name]从m_mappings中获取一个注入配置(InjectionConfig)对象
    158.             config.setResult(new InjectSingletonResult(useSingletonOf));//设置获得的注入配置(InjectionConfig)对象注入结果(InjectionResult)策略,此处设置的是InjectSingletonResult策略。
    159.             return config;//返回注入配置(InjectionConfig)对象
    160.         }
    161.         /**
    162.          * 设置类到自定义规则的映射
    163.          * @param whenAskedFor - 请求的类
    164.          * @param useRule - 自定义的规则
    165.          * @named named - 注入名,对类进一步区分,[whenAskedFor的全名+'#'+named]是映射的key
    166.          *
    167.          * @return 返回一个结果策略为InjectOtherRuleResult的注入配置(InjectionConfig)对象
    168.          * 在具体实现时会扩展InjectOtherRuleResult类
    169.          */
    170.         public function mapRule(whenAskedFor : Class, useRule : *, named : String = "") : *
    171.         {
    172.             var config : InjectionConfig = getMapping(whenAskedFor, named);
    173.             config.setResult(new InjectOtherRuleResult(useRule));
    174.             return useRule;
    175.         }
    176.         /**
    177.          * 获得一个InjectionConfig注入配置对象
    178.          * */
    179.         public function getMapping(whenAskedFor : Class, named : String = "") : InjectionConfig
    180.         {
    181.             var requestName : String = getQualifiedClassName(whenAskedFor);//获得wenAskedFor类的全名,即[包名::类名]
    182.             //如trace(getQualifiedClassName(Sprite));
    183.             //返回flash.display::Sprite
    184.             var config : InjectionConfig = m_mappings[requestName + '#' + named];
    185.             if (!config)
    186.             {
    187.                 config = m_mappings[requestName + '#' + named] =
    188.                     new InjectionConfig(whenAskedFor, named);
    189.             }
    190.             return config;
    191.            
    192.         }

    193. /**
    194.          * 向目标注入
    195.          * @param - target 目标
    196.          * */
    197.         public function injectInto(target : Object) : void
    198.         {
    199.             if (m_attendedToInjectees[target])//m_attendedToInjectee中是否有这个对象
    200.             {
    201.                 return;//如果有则返回,说明已经注入过了
    202.             }
    203.             m_attendedToInjectees[target] = true;//如果没有,说明没有注入过,开始注入

    204.             //get injection points or cache them if this target's class wasn't encountered before
    205.             var targetClass : Class = getConstructor(target);//获取目标的类
    206.             var injecteeDescription : InjecteeDescription =
    207.                     m_injecteeDescriptions[targetClass] || getInjectionPoints(targetClass);//获取目标类的InjecteeDescription对象,

    208.             var injectionPoints : Array = injecteeDescription.injectionPoints;//获取注入点列表
    209.             var length : int = injectionPoints.length;
    210.             for (var i : int = 0; i < length; i++)//遍历注入点列表
    211.             {
    212.                 var injectionPoint : InjectionPoint = injectionPoints[i];//针对每一个注入点
    213.                 injectionPoint.applyInjection(target, this);//向目标注入
    214.             }

    215.         }
    216.         /**
    217.          * 实例化一个类,包括注入
    218.          * @param clazz,需要实例化的类
    219.          * */
    220.         public function instantiate(clazz:Class):*
    221.         {
    222.             var injecteeDescription : InjecteeDescription = m_injecteeDescriptions[clazz];//查找要注入的类的注入描述
    223.             if (!injecteeDescription)//如果没有
    224.             {
    225.                 injecteeDescription = getInjectionPoints(clazz);//生成要注入类的注入描述
    226.             }
    227.             var injectionPoint : InjectionPoint = injecteeDescription.ctor;//获取要注入类的构造函数注入点
    228.             var instance : * = injectionPoint.applyInjection(clazz, this);//应用构造函数注入点
    229.             injectInto(instance);//对要注入类进行注入
    230.             return instance;//返回注入的结果
    231.         }
    232.         /**
    233.          * 解除一个映射
    234.          * @param clazz,请求的类
    235.          * @param named:注入名
    236.          * */
    237.         public function unmap(clazz : Class, named : String = "") : void
    238.         {
    239.             var mapping : InjectionConfig = getConfigurationForRequest(clazz, named);//根据请求查询相应的注入配置(InjectionConfig)
    240.             if (!mapping)//如果没有找到
    241.             {
    242.                 throw new InjectorError('Error while removing an injector mapping: ' +
    243.                     'No mapping defined for class ' + getQualifiedClassName(clazz) +
    244.                     ', named "' + named + '"');//抛出异常
    245.             }
    246.             mapping.setResult(null);//如果找到,直接将该注入配置的返回策略(InjectionResult)设为null。个人认为应该还需要从mappings中删除
    247.         }
    248.         /**
    249.          * 根据请求查询是否有相应的注入配置
    250.          * @param clazz,请求的类
    251.          * @param named:注入名
    252.          *
    253.          * @return 查询的结果
    254.          * */
    255.         public function hasMapping(clazz : Class, named : String = '') : Boolean
    256.         {
    257.             var mapping : InjectionConfig = getConfigurationForRequest(clazz, named);////根据请求查询相应的注入配置(InjectionConfig)
    258.             if (!mapping)//如果没有找到
    259.             {
    260.                 return false;//返回false
    261.             }
    262.             return mapping.hasResponse(this);//如果找到,还需要检查这个注入配置是否有返回策略。
    263.         }
    264.         /**
    265.          * 从Ioc容器获得实例
    266.          * @param clazz,请求的类
    267.          * @param named:注入名
    268.          *
    269.          * @return:返回请求的对象,该对象已经完成了依赖注入
    270.          * */
    271.         public function getInstance(clazz : Class, named : String = '') : *
    272.         {
    273.             var mapping : InjectionConfig = getConfigurationForRequest(clazz, named);//获取InjectionConfig对象
    274.             if (!mapping || !mapping.hasResponse(this))//如果没有映射或者映射没有设置返回策略
    275.             {
    276.                 throw new InjectorError('Error while getting mapping response: ' +
    277.                     'No mapping defined for class ' + getQualifiedClassName(clazz) +
    278.                     ', named "' + named + '"');//抛出异常
    279.             }
    280.             return mapping.getResponse(this);//根据注入配置的返回策略返回相应的值
    281.         }
    282.       
    283.         /**
    284.          * 创建子入器
    285.          * @param applicationDomain
    286.          * @param named:注入名
    287.          *
    288.          * @return:创建的子注入器      
    289.          * * */
    290.         public function createChildInjector(applicationDomain:ApplicationDomain=null) : Injector
    291.         {
    292.             var injector : Injector = new Injector();//新建一个注入器
    293.             injector.setApplicationDomain(applicationDomain);//设置注入器的应用程序域
    294.             injector.setParentInjector(this);//将子注入器的父注入器设为自身
    295.             return injector;//返回新建的子注入器
    296.         }
    297.         /**
    298.          * 设置应用程序域
    299.          * @param applicationDomain
    300.          *
    301.          * * */
    302.         public function setApplicationDomain(applicationDomain:ApplicationDomain):void
    303.         {
    304.             m_applicationDomain = applicationDomain;//将m_applicationDomain赋值
    305.         }
    306.         /**
    307.          * 获得应用程序域
    308.          * @return 返回该注入器工作的应用程序域
    309.          *
    310.          * * */
    311.         public function getApplicationDomain():ApplicationDomain
    312.         {
    313.             return m_applicationDomain ? m_applicationDomain : ApplicationDomain.currentDomain;//如果m_applicationDomain不为null,返回m_applicationDomain
    314.             //如果m_applicationDomain为null,返回当前的与
    315.         }

    316.         /**
    317.          * 设置父注入器
    318.          * @param parentInjector 父注入器   
    319.          * * */
    320.         public function setParentInjector(parentInjector : Injector) : void
    321.         {
    322.             //restore own map of worked injectees if parent injector is removed
    323.             if (m_parentInjector && !parentInjector)//如果m_parentInjectoru不为空,即已经设置过父注入器了,且当前传入的父注入器也不为空,即需要替换父注入器
    324.             {
    325.                 m_attendedToInjectees = new Dictionary(true);//清空已经住如果的对象的缓存
    326.             }
    327.             m_parentInjector = parentInjector;//将m_parentInjector赋值为新的父注入器
    328.             //use parent's map of worked injectees
    329.             if (parentInjector)//如果赋值的新注入器不为空
    330.             {
    331.                 m_attendedToInjectees = parentInjector.attendedToInjectees;//将当前注入器的注入对象缓存设为父注入器的注入对象缓存。
    332.             }
    333.         }
    334.         /**
    335.          * 获取父注入器
    336.          * @return parentInjector 父注入器  
    337.          * * */
    338.         public function getParentInjector() : Injector
    339.         {
    340.             return m_parentInjector;
    341.         }
    342.         /**
    343.          * 清除注入点缓存
    344.          * 将INJECTION_POINTS_CACHE重新赋值
    345.          * */
    346.         public static function purgeInjectionPointsCache() : void
    347.         {
    348.             INJECTION_POINTS_CACHE = new Dictionary(true);//清空
    349.         }
    350.       

    351.         /*******************************************************************************************
    352.         *                               internal methods                                           *
    353.         *******************************************************************************************/
    354.         /**
    355.          * 根据请求,获取父注入器的注入配置
    356.          * @param whenAskedFor 请求的类
    357.          * @param named:注入名
    358.          *
    359.          * @return 查找到的注入配置
    360.          * * */
    361.         internal function getAncestorMapping(
    362.                 whenAskedFor : Class, named : String = null) : InjectionConfig
    363.         {
    364.             var parent : Injector = m_parentInjector;//获得父注入器
    365.             while (parent)//遍历所有的父注入器
    366.             {
    367.                 var parentConfig : InjectionConfig =
    368.                     parent.getConfigurationForRequest(whenAskedFor, named, false);//从父注入器中查询相应的注入配置
    369.                 if (parentConfig && parentConfig.hasOwnResponse())//如果存在注入配置且该注入配置有返回策略
    370.                 {
    371.                     return parentConfig;//返回注入配置,查询解除
    372.                 }
    373.                 parent = parent.getParentInjector();//如果没找到,继续遍历上一个父注入器
    374.             }
    375.             return null;//如果都没有,返回null
    376.         }
    377.         /**
    378.          * 获得注入过的对象的缓存
    379.          *
    380.          * @return 返回所有住如果的对象
    381.          * * */
    382.         internal function get attendedToInjectees() : Dictionary
    383.         {
    384.             return m_attendedToInjectees;//返回 m_attendedToInjectees
    385.         }

    386.       
    387.         /*******************************************************************************************
    388.         *                               private methods                                            *
    389.         *******************************************************************************************/
    390.       
    391.         /**
    392.          * 获取一个类的注入点
    393.          * @param clazz,需要获取注入点的类
    394.          * 返回一个InjecteeDescription对象来描述所有的注入点
    395.          * */
    396.         private function getInjectionPoints(clazz : Class) : InjecteeDescription
    397.         {
    398.             var description : XML = describeType(clazz);//获取clazz的xml描述类型
    399.             if (description.@name != 'Object' && description.factory.extendsClass.length() == 0)//如果name属性不是Object且description.factory.extendsClass的长度为0,即clazz是一个接口
    400.             {
    401.                 throw new InjectorError('Interfaces can\'t be used as instantiatable classes.');//抛出异常,接口不能被注入
    402.                 /**
    403.                  * 如果是一个接口,如IEventDispatcher
    404.                  *
    405.                     <type name="flash.events::IEventDispatcher" base="Class" isDynamic="true" isFinal="true" isStatic="true">
    406.                         <extendsClass type="Class"/>
    407.                         <extendsClass type="Object"/>
    408.                         <accessor name="prototype" access="readonly" type="*" declaredBy="Class"/>
    409.                         <factory type="flash.events::IEventDispatcher">
    410.                             <method name="willTrigger" declaredBy="flash.events::IEventDispatcher" returnType="Boolean" uri="flash.events:IEventDispatcher">
    411.                             <parameter index="1" type="String" optional="false"/>
    412.                             </method>
    413.                             <method name="dispatchEvent" declaredBy="flash.events::IEventDispatcher" returnType="Boolean" uri="flash.events:IEventDispatcher">
    414.                               <parameter index="1" type="flash.events::Event" optional="false"/>
    415.                             </method>
    416.                          <method name="addEventListener" declaredBy="flash.events::IEventDispatcher" returnType="void" uri="flash.events:IEventDispatcher">
    417.                                  <parameter index="1" type="String" optional="false"/>
    418.                                  <parameter index="2" type="Function" optional="false"/>
    419.                                  <parameter index="3" type="Boolean" optional="true"/>
    420.                                  <parameter index="4" type="int" optional="true"/>
    421.                                  <parameter index="5" type="Boolean" optional="true"/>
    422.                          </method>
    423.                          <method name="hasEventListener" declaredBy="flash.events::IEventDispatcher" returnType="Boolean" uri="flash.events:IEventDispatcher">
    424.                                  <parameter index="1" type="String" optional="false"/>
    425.                          </method>
    426.                          <method name="removeEventListener" declaredBy="flash.events::IEventDispatcher" returnType="void" uri="flash.events:IEventDispatcher">
    427.                                  <parameter index="1" type="String" optional="false"/>
    428.                                  <parameter index="2" type="Function" optional="false"/>
    429.                                  <parameter index="3" type="Boolean" optional="true"/>
    430.                             </method>
    431.                         </factory>
    432.                     </type>
    433.                  * 以上为返回值factory.extendsClass为0
    434.                  *
    435.                  * 如果是一个Object
    436.                  *
    437.                     <type name="Object" base="Class" isDynamic="true" isFinal="true" isStatic="true">
    438.                       <extendsClass type="Class"/>
    439.                       <extendsClass type="Object"/>
    440.                       <constant name="length" type="int"/>
    441.                       <accessor name="prototype" access="readonly" type="*" declaredBy="Class"/>
    442.                       <factory type="Object"/>
    443.                     </type>
    444.                  * factory.extendsClass为0且@name为Object
    445.                  * 其他对象都不会
    446.                  * 故这种方法可以判断是否为接口
    447.                  * */
    448.             }
    449.             var injectionPoints : Array = [];//注入点列表
    450.             var node : XML;//节点
    451.            
    452.             // This is where we have to wire in the XML...
    453.             if(m_xmlMetadata)//如果有预先设置了,m_xmlMetadata
    454.             {
    455.                 createInjectionPointsFromConfigXML(description);//调用createInjectionPointsFromConfigXML方法
    456.                 //传输这个类的description XML的目的在于需要清除所有的元数据标签,从而只从XML中进行配置
    457.                 addParentInjectionPoints(description, injectionPoints);//继续添加父类的注入点。因为元数据标签的消失,所以需要遍历所有的父类。
    458.                 //如果不使用m_xmlMetadata,元数据会自动被子类继承,则无需使用这一步
    459.             }

    460.             //get constructor injections
    461.             var ctorInjectionPoint : InjectionPoint;//构造函数注入点
    462.             node = description.factory.constructor[0];
    463.             if (node)//如果有description.factory.constructor
    464.             {
    465.                 ctorInjectionPoint = new ConstructorInjectionPoint(node, clazz, this);//新建一个有参数的构造函数注入点
    466.             }
    467.             else
    468.             {
    469.                 ctorInjectionPoint = new NoParamsConstructorInjectionPoint();//构造函数注入点为NoParamsConstructorInjectionPoint对象,即无参数的构造函数注入点对象
    470.             }
    471.             var injectionPoint : InjectionPoint;//申明注入点
    472.             //get injection points for variables
    473.             for each (node in description.factory.*.
    474.                 (name() == 'variable' || name() == 'accessor').metadata.(@name == 'Inject'))//对于variable或者accessor结点中metadata的name是Inject的节点
    475.             {
    476.                 injectionPoint = new PropertyInjectionPoint(node);//注入点为PropertyInjectionPoint对象,即属性注入点对象
    477.                 injectionPoints.push(injectionPoint);//在注入点队列中添加改注入点
    478.             }
    479.       
    480.             //get injection points for methods
    481.            
    482.             for each (node in description.factory.method.metadata.(@name == 'Inject'))//遍历所有的Method节点中name为Inject的
    483.             {
    484.                
    485.                 injectionPoint = new MethodInjectionPoint(node, this);//注入点为MethodInjectionPoint对象,即方法注入点
    486.                 injectionPoints.push(injectionPoint);//在注入点队列中添加该注入点
    487.             }
    488.            
    489.             //get post construct methods
    490.             var postConstructMethodPoints : Array = [];//post Construct 方法注入点
    491.             for each (node in description.factory.method.metadata.(@name == 'PostConstruct'))//遍历所有PostConstruct的方法
    492.             {
    493.                 injectionPoint = new PostConstructInjectionPoint(node, this);//以node新建一个PostConstructInjectionPoint对象
    494.                 postConstructMethodPoints.push(injectionPoint);//将PostConstructInjectionPoint对象加入到postConstructMethodPoints postConstruct方法注入点列表中。
    495.             }
    496.             if (postConstructMethodPoints.length > 0)//如果有PostConstructInjectionPoint注册点
    497.             {
    498.                 postConstructMethodPoints.sortOn("order", Array.NUMERIC);//根据order属性采用数值进排序
    499.                 injectionPoints.push.apply(injectionPoints, postConstructMethodPoints);//将排序后的postConstructMethodPoinst添加到注入点中
    500.                
    501.                 /**
    502.                  * 上面这种写法是将postConstructMethodPoints中的每一个值push到injectionPoints中,此时injectionPoints的长度是增加postConstructMethodPoints.length
    503.                  * 如果直接injectionPoints.push(postConstructMethodPoints)就是将整个postConstructMethodPoints push进去,此时injectionPoints的长度是增加1
    504.                  * */
    505.                
    506.             }

    507.             var injecteeDescription : InjecteeDescription =
    508.                     new InjecteeDescription(ctorInjectionPoint, injectionPoints);//生成该类注入点描述对象
    509.             m_injecteeDescriptions[clazz] = injecteeDescription;//在m_injecteeDescriptions中将该类和其注入点描述对象进行映射
    510.             return injecteeDescription;//返回注入点描述文件
    511.         }

    512.         /**
    513.          * 根据请求获得相应的注入配置
    514.          *
    515.          * @param clazz 请求的类
    516.          * @param named 注入名
    517.          * @param traverseAncestors 是否遍历父注入器
    518.          *
    519.          * @return 返回找到的注入配置
    520.          * */
    521.       
    522.         private function getConfigurationForRequest(
    523.             clazz : Class, named : String, traverseAncestors : Boolean = true) : InjectionConfig
    524.         {
    525.             var requestName : String = getQualifiedClassName(clazz);//获取类名
    526.             var config:InjectionConfig = m_mappings[requestName + '#' + named];//获取映射
    527.            
    528.             if(!config && traverseAncestors &&
    529.                 m_parentInjector && m_parentInjector.hasMapping(clazz, named))//如果没有映射
    530.             {
    531.                 config = getAncestorMapping(clazz, named);//从辅助器中进行遍历
    532.             }
    533.             return config;//返回映射
    534.         }
    535.         /**
    536.          * 从配置的XML中获取注入点
    537.          * 先擦出所有的元数据信息,然后再根据xml写入相应的元数据
    538.          * @param description 类的描述信息
    539.          * */
    540.         private function createInjectionPointsFromConfigXML(description : XML) : void
    541.         {
    542.             var node : XML;
    543.             //first, clear out all "Inject" metadata, we want a clean slate to have the result
    544.             //work the same in the Flash IDE and MXMLC
    545.             for each (node in description..metadata.(@name=='Inject' || @name=='PostConstruct'))//遍历类的描述XML中所有的name为Inject和PostConstruct的节点
    546.             {
    547.                 delete node.parent().metadata.(@name=='Inject' || @name=='PostConstruct')[0];//清空这些节点,应为现在要根据xml来配置注入点,所以要消除元数据注入点的干扰
    548.             }
    549.            
    550.             //now, we create the new injection points based on the given xml file
    551.             var className:String = description.factory.@type;//获取类名
    552.             for each (node in m_xmlMetadata.type.(@name == className).children())//遍历配置XML中有关这个类的节点的所有子节点
    553.             {
    554.                 var metaNode : XML = <metadata/>;//新建一个metadata节点
    555.                 if (node.name() == 'postconstruct')//如果name是postconstruct
    556.                 {
    557.                     metaNode.@name = 'PostConstruct';//新建节点的name设为PostConstruct
    558.                     if (node.@order.length())
    559.                     {
    560.                         metaNode.appendChild(<arg key='order' value={node.@order}/>);//添加postConstruct的数据
    561.                     }
    562.                 }
    563.                 else//如果不是postconstrut
    564.                 {
    565.                     metaNode.@name = 'Inject';//新建节点的name设为Inject
    566.                     if (node.@injectionname.length())//如果有注入名
    567.                     {
    568.                         metaNode.appendChild(<arg key='name' value={node.@injectionname}/>);//添加注入名
    569.                     }
    570.                     for each (var arg : XML in node.arg)
    571.                     {
    572.                         metaNode.appendChild(<arg key='name' value={arg.@injectionname}/>);//添加Inject数据
    573.                     }
    574.                 }
    575.                 var typeNode : XML;
    576.                 if (node.name() == 'constructor')//如果name为constuctor
    577.                 {
    578.                     typeNode = description.factory[0];//将整个节点赋值给typeNode
    579.                 }
    580.                 else//如果不是
    581.                 {
    582.                     typeNode = description.factory.*.(attribute('name') == node.@name)[0];//将同名的节点赋值给typeNode
    583.                     if (!typeNode)//如果也没有
    584.                     {
    585.                         throw new InjectorError('Error in XML configuration: Class "' + className +
    586.                             '" doesn\'t contain the instance member "' + node.@name + '"');//抛出异常
    587.                     }
    588.                 }
    589.                 typeNode.appendChild(metaNode);//添加元数据节点
    590.             }
    591.         }
    592.         /**
    593.          * 添加父类的注入点
    594.          *
    595.          * */
    596.         private function addParentInjectionPoints(description : XML, injectionPoints : Array) : void
    597.         {
    598.             var parentClassName : String = description.factory.extendsClass.@type[0];//获取父类的类名
    599.             if (!parentClassName)//如果没有则返回
    600.             {
    601.                 return;
    602.             }
    603.             //如果有付烈
    604.             var parentClass : Class = Class(getDefinitionByName(parentClassName));//通过反射获得父类
    605.             var parentDescription : InjecteeDescription =
    606.                     m_injecteeDescriptions[parentClass] || getInjectionPoints(parentClass);//获得父类的注入点
    607.             var parentInjectionPoints : Array = parentDescription.injectionPoints;

    608.             injectionPoints.push.apply(injectionPoints, parentInjectionPoints);//点加到子类的注入点中。
    609.         }
    610.     }
    611. }

    612. import org.swiftsuspenders.injectionpoints.InjectionPoint;

    613. /**
    614. * 注入员描述类
    615. * */
    616. final class InjecteeDescription
    617. {
    618.     /**
    619.      * 构造函数注入点
    620.      * */
    621.     public var ctor : InjectionPoint;
    622.     /**
    623.      * 属性或方法注入点
    624.      * */
    625.     public var injectionPoints : Array;

    626.     public function InjecteeDescription(ctor : InjectionPoint, injectionPoints : Array)
    627.     {
    628.         this.ctor = ctor;//构造函数注入点
    629.         this.injectionPoints = injectionPoints;//剩余的属性和方法注入点
    630.     }
    631. }
    复制代码


    守望者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
    金币
    52692
    钢镚
    1422

    开源英雄守望者

    地板
     楼主| 发表于 2015-1-10 21:30:39 | 只看该作者
    InjectionConfig

    InjectionConfig是注入配置类,负责存储一个映射的相关信息,如请求的类,注入名,工作的注入器和结果返回策略等。通过注入器的mapClass等方法就会新建一个注入配置。并且注入器会缓存这些注入配置。从而在需要时调用以获得相应的对象。

             InjectionConfig公共属性如下:

    属性名
    功能
    request : Class
    请求的类
    injectionName : String
    注入名

             InjectionConfig[类的全名+#+注入名作为唯一的标识。类的全名就是包名::类名,如Sprite的全名就是flash.display::Sprite

             InjectionConfig私有属性如下:

    属性名
    功能
    m_injector : Injector
    工作的注入器,如果这个属性被设置的话,被设置的注入器对这个注入配置有最高的优先级。在getResponse时,会直接调用这个注入器,而不是当做参数传入的注入器
    m_result : InjectionResult
    返回策略。如一个类映射,该值就是InjectionClassResult,以此类推。一个注入配置必须要有一个返回策略才算是有效的注入配置,如果该值是空,在注入器看来这个注入配置就是一个无效配置

             InjectionConfig公共方法如下:

    方法名
    功能
    InjectionConfig(request : Class, injectionName : String)
    构造函数,新建一个注入配置,出事话请求的类和注入名
    getResponse(injector : Injector) : Object
    获得请求的结果,优先以m_injector作为注入器查找结果,如果没有m_injector,则以当参数传入的注入器查找,如果没有,就查找m_injector的父注入器中查找,最后再以当参数传入的注入器的父注入器中查找。
    hasResponse(injector : Injector) : Boolean
    检查是否可以返回一个请求结果。首先检查自身是否有返回策略,如果没有,就会检查父注入器中是否有相应的有效注入配置
    hasOwnResponse() : Boolean
    检查是否自身就可以返回结果,而不需要调用父注入器的注入配置
    setResult(result : InjectionResult) : void
    设置返回策略。
    setInjector(injector : Injector) : void
    设置该诸如配置工作的注入器环境

    InjectionConfig类完整注释如下:

    1. /*
    2. * Copyright (c) 2009 the original author or authors
    3. *
    4. * Permission is hereby granted to use, modify, and distribute this file
    5. * in accordance with the terms of the license agreement accompanying it.
    6. */

    7. package org.swiftsuspenders
    8. {
    9.     import flash.utils.getQualifiedClassName;

    10.     import org.swiftsuspenders.injectionresults.InjectionResult;

    11.     public class InjectionConfig
    12.     {
    13.         /*******************************************************************************************
    14.          *                              public properties                                          *
    15.          *******************************************************************************************/
    16.         public var request : Class;//请求的类
    17.         public var injectionName : String;//注入名


    18.         /*******************************************************************************************
    19.          *                              private properties                                         *
    20.          *******************************************************************************************/
    21.         private var m_injector : Injector;//工作的注入器,如果设置了,在getResonse时优先在该注入器上工作。如果没有,则使用传入的注入器
    22.         private var m_result : InjectionResult;//返回对象策略


    23.         /*******************************************************************************************
    24.          *                              public methods                                             *
    25.          *******************************************************************************************/
    26.         public function InjectionConfig(request : Class, injectionName : String)
    27.         {
    28.             this.request = request;
    29.             this.injectionName = injectionName;
    30.         }

    31.         /**
    32.          * InjectionConfig对象获取反馈对象方法
    33.          * @param injector - 注入容器
    34.          * */
    35.         public function getResponse(injector : Injector) : Object
    36.         {
    37.             if (m_result)//如果有m_result
    38.             {
    39.                 return m_result.getResponse(m_injector || injector);//如果有m_injector,以m_injecotor返回,不然以injector返回
    40.             }
    41.             //如果没有m_result,即没有设置策略
    42.             var parentConfig : InjectionConfig =
    43.                 (m_injector || injector).getAncestorMapping(request, injectionName);//从m_injector或者injector中得到有效祖先的映射
    44.             if (parentConfig)//如果有祖先映射
    45.             {
    46.                 return parentConfig.getResponse(injector);//从祖先映射中获取对象并返回
    47.             }
    48.            
    49.             return null;//如果啥都没有,返回null
    50.         }
    51.       
    52.         /**
    53.          * 检查是否有可以返回结果
    54.          * @param injector - 注入容器
    55.          * @return 返回是否可以返回结果
    56.          * */
    57.         public function hasResponse(injector : Injector) : Boolean
    58.         {
    59.             if (m_result)//如果有m_result
    60.             {
    61.                 return true;//可以
    62.             }
    63.             var parentConfig : InjectionConfig =
    64.                 (m_injector || injector).getAncestorMapping(request, injectionName);//从m_injector或者injector的父注入器中查找有效注入配置
    65.             return parentConfig != null;//如果有则会调用父注入器的有效注入配置
    66.         }
    67.         /**
    68.          * 检查是否有可以仅凭自身返回结果,不需要查找父注入器
    69.          * @return 返回是否可以仅凭自身就返回结果
    70.          * */
    71.         public function hasOwnResponse() : Boolean
    72.         {
    73.             return m_result != null;//返回是否有m_result
    74.         }
    75.         /**
    76.          * 设置返回策略
    77.          * @param result - 返回的策略
    78.          * */
    79.         public function setResult(result : InjectionResult) : void
    80.         {
    81.             if (m_result != null && result != null)//如果m_result不为空且当且设置的不为空,即要替换
    82.             {
    83.                 trace('Warning: Injector already has a rule for type "' +
    84.                         getQualifiedClassName(request) + '", named "' + injectionName + '".\n ' +
    85.                         'If you have overwritten this mapping intentionally you can use ' +
    86.                         '"injector.unmap()" prior to your replacement mapping in order to ' +
    87.                         'avoid seeing this message.');//抛出警告,建议先调用unmap方法解除映射,然后再进行映射
    88.             }
    89.             m_result = result;//无论如何都会设置m_result
    90.            
    91.         }

    92.         /**
    93.          * 设置工作的注入器环境
    94.          * @param injector - 设置的注入器
    95.          * */
    96.         public function setInjector(injector : Injector) : void
    97.         {
    98.             m_injector = injector;//对m_injector赋值
    99.         }
    100.     }
    101. }
    复制代码
    InjectionType

             InjectionType枚举了注入的映射类型。但是根本就没有用到。因此不具体阐述。

    InjectorError

             InjectorError是注入异常。仅仅扩展了Error类,其他什么都没干。不具体阐述。

    Reflector

             Relector类中包含于反射相关的一些函数。但是在框架中也没有用到,因此不具体阐述。

    getConstructor

             getConstructor函数可以获取一个对象对应的类。其机制参见http://sswilliam.blog.163.com/blog/static/18969638320116311531950/

    每一个对象都有一个constructor属性指向他的类。但是ProxyNumber, XML,和XMLList在调用constructor时会有不同的问题,解决的方案就是先获取对象的全面,然后通过getDefinitionByName来反射寻找相应的类。


    守望者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
    金币
    52692
    钢镚
    1422

    开源英雄守望者

    5#
     楼主| 发表于 2015-1-10 21:32:31 | 只看该作者
    InjectionPoint

             InjectionPoint类是所有注入点的父类,是一个抽象类。ConstructorInjectionPoint构造函数注入点,NoParamsConstructorInjectionPoint无参数的构造函数注入点,MethodInjectionPoint方法注入点,PropertyInjectionPoint属性注入点,PostConstructInjectionPointPostConstruct注入点都是InjectionPoint的子类,通过重写initalizeInjection方法实现不同的注入点的相关功能。同是会重写applyInjection方法风别实现相应注入点的注入。

             InjectionPoint公共方法

    方法名
    功能
    InjectionPoint(node : XML, injector : Injector)
    构造函数,通过传入包含注入信息的xml节点,通过调用initializeInjection方法初始化注入点,initializeInjection是个钩子方法,通过不同的子类重写从而实现不同的注入点。
    applyInjection(target : Object, injector : Injector) : Object
    抽象的应用注入方法,由子类重写,从而实现不同注入点的注入
    initializeInjection(node : XML) : void
    初始化注入点,由子类重写,从而实现不同注入点的注入

    InjectionPoint类完整注释如下:

    1. /*
    2. * Copyright (c) 2009 the original author or authors
    3. *
    4. * Permission is hereby granted to use, modify, and distribute this file
    5. * in accordance with the terms of the license agreement accompanying it.
    6. */

    7. package org.swiftsuspenders.injectionpoints
    8. {
    9.     import org.swiftsuspenders.Injector;

    10.     /**
    11.      * 注入点父类,抽象类,传入xml和Injector对象,调用initializeInjection钩子方法,采用模板方法
    12.      * */
    13.     public class InjectionPoint
    14.     {
    15.         /*******************************************************************************************
    16.         *                               public methods                                             *
    17.         *******************************************************************************************/
    18.         public function InjectionPoint(node : XML, injector : Injector)
    19.         {
    20.             initializeInjection(node);
    21.         }
    22.         /**
    23.          * 抽象应用注入方发
    24.          * @param target - 注入目标
    25.          * @param injector - 注入器对象
    26.          * @return target 返回结果
    27.          * */
    28.         public function applyInjection(target : Object, injector : Injector) : Object
    29.         {
    30.             return target;//返回注入目标
    31.         }


    32.         /*******************************************************************************************
    33.         *                               protected methods                                          *
    34.         *******************************************************************************************/
    35.         /**
    36.          * 抽象钩子方法,由子类实现,以一个带有注入信息的xml作为参数
    37.          * */
    38.         protected function initializeInjection(node : XML) : void
    39.         {
    40.         }
    41.     }
    42. }
    复制代码
    PropertyInjectionPoint

             PropertyInjectionPoint是属性注入点,被[Inject]标记公共属性和setter方法都属于属性注入点。公共属性和setter方法在通过describeType方法得到的xml中,节点的name属性的值都是property。因此把他们都归于属性注入点。

    PropertyInjectionPoint私有属性如下:

    [Inject(name='haha')]public var a:A;为例

    属性名
    功能
    _propertyName : String
    注入点名称,就是a
    _propertyType : String
    注入点的类型,就是A
    _injectionName : String;
    注入名,就是haha

    PropertyInjectionPoint主要方法如下:

    方法名
    功能
    PropertyInjectionPoint(node : XML, injector : Injector = null)
    构造函数,调用父类构造函数,初始化对象
    applyInjection(target : Object, injector : Injector) : Object
    重写的应用注入方法,针对属性注入点,直接将对象里面的注入点名称的那个属性赋值即可。所赋的值是通过injector得到的,因此如果所赋的值仍然需要依赖注入的话,会先注入那个需要的值,然后再将这个值注入进目标对象。
    initializeInjection(node : XML)
    初始化注入点,根据XML的信息,分别得到_propertyName, _propertyType_injectionName的值

    PropertyInjectionPoint类完整注释如下:

    1. /*
    2. * Copyright (c) 2009 the original author or authors
    3. *
    4. * Permission is hereby granted to use, modify, and distribute this file
    5. * in accordance with the terms of the license agreement accompanying it.
    6. */

    7. package org.swiftsuspenders.injectionpoints
    8. {
    9.     import org.swiftsuspenders.InjectionConfig;
    10.     import org.swiftsuspenders.Injector;
    11.     import org.swiftsuspenders.InjectorError;

    12.     /**
    13.      * 属性注入点
    14.      * */
    15.     public class PropertyInjectionPoint extends InjectionPoint
    16.     {
    17.         /*******************************************************************************************
    18.         *                               private properties                                         *
    19.         *******************************************************************************************/
    20.       
    21.         private var _propertyName : String;//注入点名称
    22.         private var _propertyType : String;//注入点的类型
    23.         private var _injectionName : String;//注入名

    24.       
    25.         /*******************************************************************************************
    26.         *                               public methods                                             *
    27.         *******************************************************************************************/
    28.         /**
    29.          * 构造函数
    30.          * */
    31.         public function PropertyInjectionPoint(node : XML, injector : Injector = null)
    32.         {
    33.             super(node, null);//会调用initializeInjection(node)方法
    34.         }
    35.         /**
    36.          * 属性注入点应用注入函数
    37.          * @param target - 被注入的对此昂
    38.          * @param injector - injector对象,注入容器
    39.          * @return 返回被注入的对象
    40.          * */
    41.         override public function applyInjection(target : Object, injector : Injector) : Object
    42.         {
    43.             var injectionConfig : InjectionConfig = injector.getMapping(Class(
    44.                     injector.getApplicationDomain().getDefinition(_propertyType)), _injectionName);//从injector中获取映射的InjectionConfig对象
    45.             var injection : Object = injectionConfig.getResponse(injector);//从InjectionConfig对象中获取实例
    46. //         
    47.             if (injection == null)//如果injection为空
    48.             {
    49.                 throw(new InjectorError(
    50.                         'Injector is missing a rule to handle injection into property "' +
    51.                         _propertyName + '" of object "' + target +
    52.                         '". Target dependency: "' + _propertyType + '", named "' + _injectionName +
    53.                         '"'));//抛出异常
    54.             }
    55.             target[_propertyName] = injection;//具体注入,将target._propertyName赋值为injection
    56.             return target;//返回target实际上target已经改变
    57.         }


    58.         /*******************************************************************************************
    59.         *                               protected methods                                          *
    60.         *******************************************************************************************/
    61.         /**
    62.          * 通过xml初始化注入,初始化属性注入点
    63.          *  @param node - 是metadata name为 Inject的节点
    64.          * */
    65.         override protected function initializeInjection(node : XML) : void
    66.         {
    67.             /**
    68.             * _propertyType:属性类型
    69.             * _propertyName:属性名称
    70.             * _injectionName:注入名
    71.             * 如:
    72.             * [Inject(name='haha')]public var a:A;
    73.             * A就是属性类型
    74.             * a就是属性名称
    75.             * haha就是注入名,就是在mapClass后面的最后一个参数
    76.             * 改node的的值是<metadata name="Inject"/>
    77.             * 其parent就包含了整个属性的类型描述
    78.             * 如:
    79.             <variable name="property" type="org.swiftsuspenders.support.types::Clazz">
    80.               <metadata name="Inject">
    81.                 <arg key="name" value="haha"/>
    82.               </metadata>
    83.               <metadata name="__go_to_definition_help">
    84.                 <arg key="pos" value="1312"/>
    85.               </metadata>
    86.             </variable>
    87.             * */
    88.             _propertyType = node.parent().@type.toString();//设置注入点的类型
    89.             _propertyName = node.parent().@name.toString();//设置注入点名称
    90.             _injectionName = node.arg.attribute('value').toString();//设置注入名
    91.         }
    92.     }
    93. }
    复制代码


    守望者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
    金币
    52692
    钢镚
    1422

    开源英雄守望者

    6#
     楼主| 发表于 2015-1-10 21:34:08 | 只看该作者
    MethodInjectionPoint

             MethodInjectionPoint是方法注入点,被[Inject]标记公共方法都属于方法注入点。公共方法在通过describeType方法得到的xml中,节点的name属性的值都是method

    MethodInjectionPoint受保护属性如下:

    属性名
    功能
    methodName : String
    注入点名称,就是方法名
    _parameterInjectionConfigs : Array
    注入参数,与属性注入点不同,方法注入点可以有多个参数
    requiredParameters : int
    需要的参数数

    MethodInjectionPoint主要方法如下:

    方法名
    功能
    MethodInjectionPoint (node : XML, injector : Injector = null)
    构造函数,调用父类构造函数,初始化对象
    applyInjection(target : Object, injector : Injector) : Object
    重写的应用注入方法,针对方法注入点,首先先回获取函数的参数值,然后得到函数的应用,最后调用apply方法执行函数从而完成注入。
    initializeInjection(node : XML)
    初始化注入点,根据XML的信息,分别得到得到methodName信息,然后会调用gatherParameters方法获得该函数的参数
    gatherParameters(
    methodNode : XML, nameArgs : XMLList)
    通过解析XML的信息获得注入函数所需的参数名称,包括是否该参数包含注入名
    gatherParameterValues(
    target : Object, injector : Injector)
    获取函数参数的值。通过注入器获取相应的对象,这样如果参数的值任然需要依赖注入,就会先对这些值进行注入,存储到_parameterInjectionConfigs以供注入

    MethodInjectionPoint包外类ParameterInjectionConfig:这个类包含了对方法注入的每个参数的注入信息,包括参数名和注入名,以方便注入使用。

    MethodInjectionPoint类完整注释如下:

    1. /*
    2. * Copyright (c) 2009 the original author or authors
    3. *
    4. * Permission is hereby granted to use, modify, and distribute this file
    5. * in accordance with the terms of the license agreement accompanying it.
    6. */

    7. package org.swiftsuspenders.injectionpoints
    8. {
    9.     import flash.utils.getQualifiedClassName;

    10.     import org.swiftsuspenders.InjectionConfig;
    11.     import org.swiftsuspenders.Injector;
    12.     import org.swiftsuspenders.InjectorError;

    13.     /**
    14.      * 方法注入点
    15.      * */
    16.     public class MethodInjectionPoint extends InjectionPoint
    17.     {
    18.         /*******************************************************************************************
    19.         *                               private properties                                         *
    20.         *******************************************************************************************/
    21.         /**
    22.          * 方法名
    23.          * */
    24.         protected var methodName : String;
    25.         /**
    26.          *
    27.          * */
    28.         protected var _parameterInjectionConfigs : Array;//该函数注入点参数注入配置
    29.         protected var requiredParameters : int = 0;//如要的参数数
    30.       
    31.       
    32.         /*******************************************************************************************
    33.         *                               public methods                                             *
    34.         *******************************************************************************************/
    35.         public function MethodInjectionPoint(node : XML, injector : Injector = null)
    36.         {
    37.             super(node, injector);
    38.         }
    39.         /**
    40.          * 方法注入点应用注入函数
    41.          * @param target - 被注入的对象
    42.          * @param injector - 注入器
    43.          * @return 返回被注入的对象
    44.          * */
    45.         override public function applyInjection(target : Object, injector : Injector) : Object
    46.         {
    47.             var parameters : Array = gatherParameterValues(target, injector);//获取参数的值
    48.             var method : Function = target[methodName];//获取需要注入的函数
    49.             method.apply(target, parameters);//按照参数来调用函数
    50.             return target;//返回目标,此时已经调用输入函数
    51.         }


    52.         /*******************************************************************************************
    53.         *                               protected methods                                          *
    54.         *******************************************************************************************/
    55.         /**
    56.          * 通过xml初始化注入,初始化方法注入点
    57.          * @param node - 是metadata name为 Inject的节点
    58.          * */
    59.         override protected function initializeInjection(node : XML) : void
    60.         {
    61.             var nameArgs : XMLList = node.arg.(@key == 'name');//获取参数名
    62.             var methodNode : XML = node.parent();//获取父节点
    63.             methodName = methodNode.@name.toString();//获取注入方法方法名
    64.             gatherParameters(methodNode, nameArgs);//获取参数
    65.         }
    66.         /**
    67.          * 获取参数,实际是向_parameterInjectionConfigs赋值,包涵了该函数注入点的参数名
    68.          * @param node
    69.          * 如一个方法注入的xml描述如下
    70.          * <method name="setDependencies" declaredBy="org.swiftsuspenders.support.injectees::TwoParametersMethodInjectee" returnType="void">
    71.               <parameter index="1" type="org.swiftsuspenders.support.types::Clazz" optional="false"/>
    72.               <parameter index="2" type="org.swiftsuspenders.support.types::Interface" optional="false"/>
    73.               <metadata name="Inject">
    74.                 <arg key="name" value="haha"/>
    75.               </metadata>
    76.               <metadata name="__go_to_definition_help">
    77.                 <arg key="pos" value="1467"/>
    78.               </metadata>
    79.             </method>
    80.          * 有两个参数,切optional都是false
    81.          * 一个类型是clazz,还有一个是Intrface,
    82.          * Inject的参数中name参数就是每个注入参数分别的注入名
    83.          * 如
    84.          * [Inject(name="haha",name="haha2")]
    85.             public function setDependencies(dependency:Clazz, dependency2:Interface):void
    86.             {
    87.                 m_dependency = dependency;
    88.                 m_dependency2 = dependency2;
    89.             }
    90.          * 则此时dependency的注入名为haha,dependency2的注入名为haha2
    91.          * injector的映射此时就要有注入名的隐射,如:
    92.             var inj:Injector = new Injector();
    93.             inj.mapSingleton(Clazz,"haha");
    94.             inj.mapClass(Interface,Clazz2,"haha2");
    95.             inj.injectInto(injectee);
    96.          * */
    97.         protected function gatherParameters(methodNode : XML, nameArgs : XMLList) : void
    98.         {
    99.             _parameterInjectionConfigs = [];//清空参数
    100.             var i : int = 0;
    101.             for each (var parameter : XML in methodNode.parameter)//遍历parameter节点
    102.             {
    103.                 var injectionName : String = '';//初始化注入名
    104.                 if (nameArgs[i])//如果nameArgs第i位有
    105.                 {
    106.                     injectionName = nameArgs[i].@value.toString();//注入名就是nameArgs[i]的value属性
    107.                   
    108.                 }
    109.                 var parameterTypeName : String = parameter.@type.toString();//参数类型名是param的type属性
    110.                 if (parameterTypeName == '*')//如果类型是*
    111.                 {
    112.                     if (parameter.@optional.toString() == 'false')//如果optional属性时false
    113.                     {
    114.                         //TODO: Find a way to trace name of affected class here
    115.                         throw new InjectorError('Error in method definition of injectee. ' +
    116.                             'Required parameters can\'t have type "*".')//抛出异常,取药的参数不能是*类型
    117.                     }
    118.                     else//如果optional是true
    119.                     {
    120.                         parameterTypeName = null;//类型的名称为null
    121.                     }
    122.                 }
    123.                 _parameterInjectionConfigs.push(
    124.                         new ParameterInjectionConfig(parameterTypeName, injectionName));//向参数注入配置中添加一个配置对象
    125.                 if (parameter.@optional.toString() == 'false')//如果optional属性时false
    126.                 {
    127.                     requiredParameters++;//需要的参数+1
    128.                 }
    129.                 i++;
    130.             }
    131.            
    132.         }
    133.         /**
    134.          * 获取参数的值
    135.          * @param target - 注入目标
    136.          * @param injector - 注入器
    137.          *
    138.          * */
    139.         protected function gatherParameterValues(target : Object, injector : Injector) : Array
    140.         {
    141.             var parameters : Array = [];//申明返回值
    142.             var length : int = _parameterInjectionConfigs.length;//长度,就是参数诸如配置的长度
    143.             for (var i : int = 0; i < length; i++)//遍历_parameterInjectionConfigs
    144.             {
    145.                 var parameterConfig : ParameterInjectionConfig = _parameterInjectionConfigs[i];//获取第I个参数注入配置
    146.                 var config : InjectionConfig = injector.getMapping(Class(
    147.                         injector.getApplicationDomain().getDefinition(parameterConfig.typeName)),
    148.                         parameterConfig.injectionName);//从injector获得相应的注入配置,通过类和注入名来获取
    149.                 var injection : Object = config.getResponse(injector);//获得对象/
    150.                 //个人觉得直接用injector.getInstance()就可以了
    151.                 if (injection == null)//如果是空
    152.                 {
    153.                     if (i >= requiredParameters)//如果已经超出了需要的参数个数,即有可选参数
    154.                     {
    155.                         break;//直接跳出
    156.                     }//否则抛出异常
    157.                     throw(new InjectorError(
    158.                         'Injector is missing a rule to handle injection into target ' + target +
    159.                         '. Target dependency: ' + getQualifiedClassName(config.request) +
    160.                         ', method: ' + methodName + ', parameter: ' + (i + 1)
    161.                     ));
    162.                 }
    163.                
    164.                 parameters[i] = injection;//将值加入返回的参数列表
    165.             }
    166.             return parameters;//返回参数的值
    167.         }
    168.     }
    169. }

    170. /**
    171. * 参数注入配置,包涵注入参数的类型和注入名,这样就可以从injector中getInstance(Class,name)获得需要注入的对象
    172. * */
    173. final class ParameterInjectionConfig
    174. {
    175.     public var typeName : String;//类型名
    176.     public var injectionName : String;//注入名

    177.     public final function ParameterInjectionConfig(typeName : String, injectionName : String)
    178.     {
    179.         this.typeName = typeName;
    180.         this.injectionName = injectionName;
    181.     }
    182. }
    复制代码


    守望者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
    金币
    52692
    钢镚
    1422

    开源英雄守望者

    7#
     楼主| 发表于 2015-1-10 21:35:48 | 只看该作者
    ConstructorInjectionPoint

    ConstructornInjectionPoint是构造函数注入点,在类前添加[Inject]元数据标签就会申明构造函数注入点。 继承自MethodInjectionPoint

    ConstructornInjectionPoint主要方法如下:

    方法名
    功能
    ConstructorInjectionPoint(node : XML, clazz : Class, injector : Injector = null)
    构造函数,注意Flash player在一个类至少被实例化一次之前不会给出type信息。会调用createDummyInstance方法假装实例一下这个类,然后将获得的类的XML描述进行更新。
    applyInjection(target : Object, injector : Injector) : Object
    应用注入,会将注入的参数手动的new到构造函数里,注意只能有10个参数,由于构造函数无法apply,所以只能手动的来new,具体见注释
    initializeInjection(node : XML) : void
    初始化注入点,会调用父类的gatherParamenters方法来寻找到所有的要注入的参数名
    createDummyInstance(
    constructorNode : XML, clazz : Class)
    尝试实例化一个类,并且更新类的XML描述信息,以解决不能得到type信息的bug

    ConstructornInjectionPoint类完整注释如下:

    1. /*
    2. * Copyright (c) 2009 the original author or authors
    3. *
    4. * Permission is hereby granted to use, modify, and distribute this file
    5. * in accordance with the terms of the license agreement accompanying it.
    6. */

    7. package org.swiftsuspenders.injectionpoints
    8. {
    9.     import flash.utils.describeType;

    10.     import org.swiftsuspenders.Injector;
    11.     /**
    12.      * 构造函数注入点,扩展自MethodInjectionPoint
    13.      * */
    14.     public class ConstructorInjectionPoint extends MethodInjectionPoint
    15.     {
    16.         /*******************************************************************************************
    17.         *                               public methods                                             *
    18.         *******************************************************************************************/
    19.         public function ConstructorInjectionPoint(
    20.                 node : XML, clazz : Class, injector : Injector = null)
    21.         {
    22.             /*
    23.               In many cases, the flash player doesn't give us type information for constructors until
    24.               the class has been instantiated at least once. Therefore, we do just that if we don't get
    25.               type information for at least one parameter.
    26.              */
    27.             /**
    28.              * 在许多情况下,Flash player在一个类至少被实例化一次之前不会给出type信息。因此我们先假装实例一下从而来获得类型信息
    29.              * */
    30.             if (node.parameter.(@type == '*').length() == node.parameter.@type.length())//如果所有的参数类型都是*
    31.             {
    32.                 createDummyInstance(node, clazz);//调用createDummyInstance函数,以解决FP的bug
    33.             }
    34.             super(node, injector);
    35.         }
    36.       
    37.         override public function applyInjection(target : Object, injector : Injector) : Object
    38.         {
    39.             var ctor : Class = Class(target);//target是一个Class
    40.             var p : Array = gatherParameterValues(target, injector);//获得构造函数的参数的值,调用父类方法
    41.             //the only way to implement ctor injections, really!
    42.             /**
    43.              * 唯一实现构造函数注入的方法,所以只能少于10个参数的构造函数
    44.              * */
    45.             switch (p.length)
    46.             {
    47.                 case 0 : return (new ctor());
    48.                 case 1 : return (new ctor(p[0]));
    49.                 case 2 : return (new ctor(p[0], p[1]));
    50.                 case 3 : return (new ctor(p[0], p[1], p[2]));
    51.                 case 4 : return (new ctor(p[0], p[1], p[2], p[3]));
    52.                 case 5 : return (new ctor(p[0], p[1], p[2], p[3], p[4]));
    53.                 case 6 : return (new ctor(p[0], p[1], p[2], p[3], p[4], p[5]));
    54.                 case 7 : return (new ctor(p[0], p[1], p[2], p[3], p[4], p[5], p[6]));
    55.                 case 8 : return (new ctor(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]));
    56.                 case 9 : return (new ctor(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]));
    57.                 case 10 : return (new ctor(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9]));
    58.             }
    59.             return null;
    60.         }

    61.         /*******************************************************************************************
    62.         *                               protected methods                                          *
    63.         *******************************************************************************************/
    64.         override protected function initializeInjection(node : XML) : void
    65.         {
    66.             var nameArgs : XMLList = node.parent().metadata.(@name == 'Inject').arg.(@key == 'name');//获得包含参数的子节点
    67.             methodName = 'constructor';//将方法名赋值为constructor,其实不赋值也没关系,因为构造函数输入用不到这个熟悉
    68.            
    69.             gatherParameters(node, nameArgs);//获取要注入的参数名
    70.         }
    71.       
    72.         /*******************************************************************************************
    73.         *                               private methods                                            *
    74.         *******************************************************************************************/
    75.         /**
    76.          * 为了防止无法获得构造函数的type信息,从而
    77.          * */
    78.         private function createDummyInstance(constructorNode : XML, clazz : Class) : void
    79.         {
    80.             try//尝试new一下这个类,如果不行则抛出异常
    81.             {
    82.                 switch (constructorNode.children().length())
    83.                 {
    84.                     case 0 : (new clazz()); break;
    85.                     case 1 : (new clazz(null)); break;
    86.                     case 2 : (new clazz(null, null)); break;
    87.                     case 3 : (new clazz(null, null, null)); break;
    88.                     case 4 : (new clazz(null, null, null, null)); break;
    89.                     case 5 : (new clazz(null, null, null, null, null)); break;
    90.                     case 6 : (new clazz(null, null, null, null, null, null)); break;
    91.                     case 7 : (new clazz(null, null, null, null, null, null, null)); break;
    92.                     case 8 : (new clazz(null, null, null, null, null, null, null, null)); break;
    93.                     case 9 : (new clazz(null, null, null, null, null, null, null, null, null)); break;
    94.                     case 10 : (new clazz(null, null, null, null, null, null, null, null, null, null)); break;
    95.                 }
    96.             }
    97.             catch (error : Error)
    98.             {
    99.                 trace('Exception caught while trying to create dummy instance for constructor ' +
    100.                         'injection. It\'s almost certainly ok to ignore this exception, but you ' +
    101.                         'might want to restructure your constructor to prevent errors from ' +
    102.                         'happening. See the SwiftSuspenders documentation for more details. ' +
    103.                         'The caught exception was:\n' + error);
    104.             }//在new完之后,不论是否new成功,类的xml描述就可以获得了
    105.             constructorNode.setChildren(describeType(clazz).factory.constructor[0].children());//重新设置XML信息
    106.         }
    107.     }
    108. }
    复制代码
    NoParamsConstructorInjectionPoint

    NoParamsConstructornInjectionPoint是无参构造函数注入点,解决所有没有构造函数注入的类的实例化问题

    NoParamsConstructornInjectionPoint主要方法如下:

    属性名
    功能
    NoParamConstructorInjectionPoint
    构造函数,直接默认即可,因为就是为了实现new一个目标类的问题
    applyInjection(target : Object, injector : Injector) : Object
    直接new出目标类的对象并返回即可。

    很简单,就不给出注释了,直接看代码即可。

    PostConstructInjectionPoint

    PostConstructInjectionPoint表示了那些完成注入后需要执行的方法,也将他们抽象为注入点进行处理,通过[PostConstruct]标记出的方法就会被SwiftSuspenders添加为PostConstrucInjectionPoint

    PostConstructInjectionPoint主要属性如下:

    属性名
    功能
    methodName:String
    需要调用的方法名
    orderValue:int
    调用的顺序,可能一个类会有多个方法被标记为PostConstruct。通过该值决定调用方法的顺序

    PostConstructInjectionPoint主要方法如下:

    方法名
    功能
    PostConstructInjectionPoint(node:XML, injector : Injector = null)
    构造函数,直接调用父类的构造函数
    applyInjection(target : Object, injector : Injector) : Object
    直接调用目标的该方法即可,注意申明为PostConstruct的方法都是无参数的方法
    initializeInjection(node : XML)
    初始化该注入点,通过获得order参数的值得到调用的顺序
    get order():int
    获得该PostConstruct的被调用顺序的值

    PostConstructInjectionPoint主要方法如下:

    1. /*
    2. * Copyright (c) 2009 the original author or authors
    3. *
    4. * Permission is hereby granted to use, modify, and distribute this file
    5. * in accordance with the terms of the license agreement accompanying it.
    6. */

    7. package org.swiftsuspenders.injectionpoints
    8. {
    9.     import org.swiftsuspenders.Injector;
    10.    
    11.     /**
    12.      * 实际不是注入点,通过配置PostConstructInjectionPoint,可以再完成注入后执行相应的函数,order代表执行顺序顺序
    13.      * 如
    14.         [PostConstruct(order="2")]
    15.         public function post2():void{
    16.             trace("post2");
    17.         }
    18.         [PostConstruct(order="1")]
    19.         public function post1():void{
    20.             trace("post1");
    21.         }
    22.          * 当类中有这两个函数时
    23.          * 在该类完成注入时
    24.          * 就会先执行post1,再执行post2
    25.          * order决定了执行顺序
    26.      * */
    27.     public class PostConstructInjectionPoint extends InjectionPoint
    28.     {
    29.         /*******************************************************************************************
    30.          *                              private properties                                         *
    31.          *******************************************************************************************/
    32.         protected var methodName : String;//方法名
    33.         protected var orderValue:int;//顺序
    34.       
    35.       
    36.         /*******************************************************************************************
    37.          *                              public methods                                             *
    38.          *******************************************************************************************/
    39.         public function PostConstructInjectionPoint(node:XML, injector : Injector = null)
    40.         {
    41.             super(node, injector);
    42.         }
    43.       
    44.         public function get order():int
    45.         {
    46.             return orderValue;
    47.         }

    48.         override public function applyInjection(target : Object, injector : Injector) : Object
    49.         {
    50.             target[methodName]();//调用target的methodName方法
    51.             return target;
    52.         }
    53.       
    54.       
    55.         /*******************************************************************************************
    56.          *                              protected methods                                          *
    57.          *******************************************************************************************/
    58.         override protected function initializeInjection(node : XML) : void
    59.         {
    60.             var orderArg : XMLList = node.arg.(@key == 'order');//获取key是order节点
    61.             var methodNode : XML = node.parent();//获取PostConstruct XML节点
    62.             orderValue = int(orderArg.@value);//orderArg的value属性赋值给orderValue
    63.             methodName = methodNode.@name.toString();//节点的name属性赋值给method,方法名
    64.         }
    65.     }
    66. }
    复制代码


    守望者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
    金币
    52692
    钢镚
    1422

    开源英雄守望者

    8#
     楼主| 发表于 2015-1-10 21:40:12 | 只看该作者
    InjectionResult

             InjectionResult是返回策略的父类,有一个抽象的getResponse方法,各种返回结果的子类可以通过重写该方法实现相应的返回策略

             InjectionResult主要方法如下:

    方法名
    功能
    InjectionResult()
    构造函数
    getResponse(injector : Injector) : Object
    抽象方法,由子类重写以实现相应的返回策略

             类很简单,不给出注释

    InjectClassResult

             InjectClassResult会返回一个类的实例。每次调用都会将该类重新实例一次,然后返回

    InjectClassResult主要属性如下:

    属性名
    功能
    m_responseType : Class
    需要返回的类

    InjectClassResult主要方法如下:

    方法名
    功能
    InjectClassResult(responseType : Class)
    构造函数,传实例化入需要的类
    getResponse(injector : Injector) : Object
    通过调用传入的注入器的initantiate方法从注入器获得该类的实例,如果该类仍然需要注入,注入器会完成依赖注入。

    InjectClassResult完整注释如下:

    1. <font color="#000000">/*
    2. * Copyright (c) 2009 the original author or authors
    3. *
    4. * Permission is hereby granted to use, modify, and distribute this file
    5. * in accordance with the terms of the license agreement accompanying it.
    6. */

    7. package org.swiftsuspenders.injectionresults
    8. {
    9.     import org.swiftsuspenders.Injector;

    10.    
    11.     public class InjectClassResult extends InjectionResult
    12.     {
    13.         /*******************************************************************************************
    14.          *                              private properties                                         *
    15.          *******************************************************************************************/
    16.         private var m_responseType : Class;//需要实例化的类
    17.       
    18.       
    19.         /*******************************************************************************************
    20.          *                              public methods                                             *
    21.          *******************************************************************************************/
    22.         public function InjectClassResult(responseType : Class)
    23.         {
    24.             m_responseType = responseType;//赋值
    25.         }
    26.       
    27.         override public function getResponse(injector : Injector) : Object
    28.         {
    29.             return injector.instantiate(m_responseType);//通过注入器进行实例化,这样保证得到的实例是已经经过依赖注入的
    30.         }
    31.     }
    32. }</font>
    复制代码
    InjectSingletonResult

    InjectSingletonResult会返回一个类的单例对象。所有的这个对象的使用者共享这个对象。

    InjectSingletonResult主要属性如下:

    属性名
    功能
    m_responseType : Class
    需要返回的类
    m_response:Object
    单例对象的引用

    InjectSingletonResult主要方法如下:

    方法名
    功能
    InjectSingletonResult(responseType : Class)
    构造函数,传入需要实例化的类
    getResponse(injector : Injector) : Object
    返回类的单例对象
    createResponse(injector : Injector) : Object
    创建类的对象,并将其赋值给m_response,这样在调用getResponse时,如果m_response为空,就通过注入器获得该对象的实例,然后返回,如果m_response不为空,则直接返回m_response,这样实现单例的效果

             InjectSingletonResult完整注释如下:

    1. <font color="#000000">/*
    2. * Copyright (c) 2009 the original author or authors
    3. *
    4. * Permission is hereby granted to use, modify, and distribute this file
    5. * in accordance with the terms of the license agreement accompanying it.
    6. */

    7. package org.swiftsuspenders.injectionresults
    8. {
    9.     import org.swiftsuspenders.Injector;

    10.     public class InjectSingletonResult extends InjectionResult
    11.     {
    12.         /*******************************************************************************************
    13.          *                              private properties                                         *
    14.          *******************************************************************************************/
    15.         private var m_responseType : Class;//需要实例化的类
    16.         private var m_response : Object;//单例的引用
    17.       
    18.       
    19.         /*******************************************************************************************
    20.          *                              public methods                                             *
    21.          *******************************************************************************************/
    22.         public function InjectSingletonResult(responseType : Class)
    23.         {
    24.             m_responseType = responseType;//赋值
    25.         }
    26.       
    27.         override public function getResponse(injector : Injector) : Object
    28.         {
    29.             return m_response ||= createResponse(injector);//通过此种方式实现单例模式,第一次会调用instantiate方法生成一个实例,
    30.             //并对m_response进行赋值,以后值接返回m_response
    31.         }
    32.       
    33.       
    34.         /*******************************************************************************************
    35.          *                              private methods                                            *
    36.          *******************************************************************************************/
    37.         private function createResponse(injector : Injector) : Object
    38.         {
    39.             return injector.instantiate(m_responseType);//创建一个实例,通过调用注入器获得需要返回的对象,这样保证返回的对象是已经完成注入过的对象。
    40.         }
    41.     }
    42. }</font>
    复制代码
    InjectValueResult

             InjectValueResult会返回预先设定好的对象。

    InjectValueResult主要属性如下:

    属性名
    功能
    m_value : Object
    需要返回的值的引用

    InjectValueResult主要方法如下:

    方法名
    功能
    InjectValueResult(value : Object)
    构造函数,传入需要返回的对象
    getResponse(injector : Injector) : Object
    返回类需要返回的对象

    InjectValueResult完整注释如下:

    1. /*
    2. * Copyright (c) 2009 the original author or authors
    3. *
    4. * Permission is hereby granted to use, modify, and distribute this file
    5. * in accordance with the terms of the license agreement accompanying it.
    6. */

    7. package org.swiftsuspenders.injectionresults
    8. {
    9.     import org.swiftsuspenders.Injector;
    10.    
    11.     public class InjectValueResult extends InjectionResult
    12.     {
    13.         /*******************************************************************************************
    14.          *                              private properties                                         *
    15.          *******************************************************************************************/
    16.         private var m_value : Object;//需要返回的对象
    17.       
    18.       
    19.         /*******************************************************************************************
    20.          *                              public methods                                             *
    21.          *******************************************************************************************/
    22.         public function InjectValueResult(value : Object)
    23.         {
    24.             m_value = value;//设置m_value
    25.         }
    26.       
    27.         override public function getResponse(injector : Injector) : Object
    28.         {
    29.             return m_value;//返回m_value
    30.         }
    31.     }
    32. }
    复制代码
    InjectOtherRuleResult

    InjectOtherRuleResult会调用另外的注入配置的返回策略,从而达到复用的效果。同时也可以通过在InjectConfig中设置自定义的返回策略而扩展框架。不过个人感觉这个功能比较鸡肋。没有太大的用处。

    InjectOtherRuleResult主要属性如下:

    属性名
    功能
    m_rule : InjectionConfig
    需要复用的注入配置对象

    InjectOtherRuleResult主要方法如下:

    方法名
    功能
    InjectOtherRuleResult(rule : InjectionConfig)
    构造函数,传入需要返回的注入配置对象
    getResponse(injector : Injector) : Object
    调用注入配置的返回策略,达到复用的目的

    InjectValueResult完整注释如下:

    1. /*
    2. * Copyright (c) 2010 the original author or authors
    3. *
    4. * Permission is hereby granted to use, modify, and distribute this file
    5. * in accordance with the terms of the license agreement accompanying it.
    6. */

    7. package org.swiftsuspenders.injectionresults
    8. {
    9.     import org.swiftsuspenders.InjectionConfig;
    10.     import org.swiftsuspenders.Injector;

    11.     //其他规则,复用其他InjectionConfig的返回策略,
    12.     public class InjectOtherRuleResult extends InjectionResult
    13.     {
    14.         /*******************************************************************************************
    15.          *                              private properties                                         *
    16.          *******************************************************************************************/
    17.         private var m_rule : InjectionConfig;//其他的注入配置
    18.       
    19.       
    20.         /*******************************************************************************************
    21.          *                              public methods                                             *
    22.          *******************************************************************************************/
    23.         public function InjectOtherRuleResult(rule : InjectionConfig)
    24.         {
    25.             m_rule = rule;//设置注入配置
    26.         }
    27.       
    28.         override public function getResponse(injector : Injector) : Object
    29.         {
    30.             return m_rule.getResponse(injector);//调用其他的注入配置的返回策略
    31.         }
    32.     }
    33. }
    复制代码
    总结

             至此这篇SwiftSuspenders1.6 浅出深入就写完了。框架这个东西有利有弊,特别是对新手而言,使用框架,可以让新手很容易的加入到团队的开发中,但是如果对框架没有很好的理解,很可能会偏离框架原有的初衷。要想很好的理解框架,阅读框架的代码无疑是最直接有效的方法了,这也是我写这篇文章的目的所在。同时阅读代码,可以学习到很多编程上面的技巧和思想,对自身的提高也是很有帮助的,比如swiftSuspenders中,很多有关元数据,反射的AS的特性,在一般的开发中是很少能接触到的。我会把我注释过的源代码上传,以方便大家查阅。

             由于个人能力有限,文章中出现一些错误在所难免,欢迎大家批评指正。希望能与大家进行更多的交流。


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

    使用道具 举报

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

    本版积分规则

    
    关闭

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

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

    GMT+8, 2024-4-19 15:14 , Processed in 0.075802 second(s), 30 queries .

    守望者AIR

    守望者AIR技术交流社区

    本站成立于 2014年12月31日

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