轻量级IOC框架SwiftSuspenders
该框架的1.6版本位于https://github.com/tschneidereit/SwiftSuspenders/blob/the-past/,现在已经出了重新架构的2.0版本,所以我决定先研究已经成熟的1.6版本,有时间再研究2.0版本的。
IOC的基本知识
控制反转(Inversion of Control,英文缩写为IoC)又叫做依赖注入(Dependency Injection,英文缩写为DI),是一种降低耦合度的程序设计模式,它通过将对象的创建过程解耦出来来降低对象间的依赖关系。具体的,在文章依赖注入那些事儿里解释的很详细,另外也可参考老马的文章和深度理解依赖注入(Dependence Injection)。
describeType函数介绍
SwiftSuspenders是利用describeType函数来实现其反射机制的。
describeType函数可用来生成描述 ActionScript 对象(命名为方法的参数)的 XML 对象。利用此方法可实现 ActionScript 语言的反射编程概念。
为了详细说明这个函数,我们先自定义一个类MyClass:
public class MyClass extends Object
{
public const const_varable:int = 0;
[Inject(desc="a public varable")]
public var pub_varable:String = "";private var pri_varable:String = "";
[Inject(desc="a static function")]
public static function static_func(s:String):void
{
trace(s);
}
public function get accpri():String
{
return pri_varable;
}
public function set accpri(v:String):void
{
pri_varable = v;
}
public function TraceOut():void {
trace(accpri);
}
public function MyClass()
{
}
}
如果传入的参数是类型的实例,则返回的 XML 对象包括该类型的所有实例属性,但不包括任何静态属性。
var m:MyClass = new MyClass();
trace(describeType(m));
得到如下的XML:
<type name="MyClass" base="Object" isDynamic="false" isFinal="false" isStatic="false">
<extendsClass type="Object"/>
<constant name="const_varable" type="int">
<metadata name="__go_to_definition_help">
<arg key="pos" value="110"/>
</metadata>
</constant>
<variable name="pub_varable" type="String">
<metadata name="Inject">
<arg key="desc" value="a public varable"/>
</metadata>
<metadata name="__go_to_definition_help">
<arg key="pos" value="184"/>
</metadata>
</variable>
<accessor name="accpri" access="readwrite" type="String" declaredBy="MyClass">
<metadata name="__go_to_definition_help">
<arg key="pos" value="425"/>
</metadata>
<metadata name="__go_to_definition_help">
<arg key="pos" value="498"/>
</metadata>
</accessor>
<method name="TraceOut" declaredBy="MyClass" returnType="void">
<metadata name="__go_to_definition_help">
<arg key="pos" value="571"/>
</metadata>
</method>
<metadata name="__go_to_ctor_definition_help">
<arg key="pos" value="632"/>
</metadata>
<metadata name="__go_to_definition_help">
<arg key="pos" value="67"/>
</metadata>
</type>
忽略掉其中__go_to_ctor_definition_help形式的metadata,可以看到如下XML:
<type name="MyClass" base="Object" isDynamic="false" isFinal="false" isStatic="false">
<extendsClass type="Object"/>
<constant name="const_varable" type="int">
</constant>
<variable name="pub_varable" type="String">
<metadata name="Inject">
<arg key="desc" value="a public varable"/>
</metadata>
</variable>
<accessor name="accpri" access="readwrite" type="String" declaredBy="MyClass">
</accessor>
<method name="TraceOut" declaredBy="MyClass" returnType="void">
</method>
</type>
1.可以在解析 XML 对象时检查传入的是对象还是类,方法是检查 <type> 标签的 isStatic 属性的值,该值在 value 参数是类型的实例时为 false。
2.private属性和方法不会被describeType函数解析到。
要获取某个类型的静态属性,则传递该类型本身。返回的 XML 对象不仅仅包括类型的静态属性,而且还包括它的所有实例属性。
trace(describeType(MyClass));忽略掉其中__go_to_ctor_definition_help形式的metadata,可以得到如下XML:
<type name="MyClass" base="Class" isDynamic="true" isFinal="true" isStatic="true">
<extendsClass type="Class"/>
<extendsClass type="Object"/>
<accessor name="prototype" access="readonly" type="*" declaredBy="Class"/>
<method name="static_func" declaredBy="MyClass" returnType="void">
<parameter index="1" type="String" optional="false"/>
<metadata name="Inject">
<arg key="desc" value="a static function"/>
</metadata>
</method>
<factory type="MyClass">
<extendsClass type="Object"/>
<constant name="const_varable" type="int">
</constant>
<variable name="pub_varable" type="String">
<metadata name="Inject">
<arg key="desc" value="a public varable"/>
</metadata>
</variable>
<accessor name="accpri" access="readwrite" type="String" declaredBy="MyClass">
</accessor>
<method name="TraceOut" declaredBy="MyClass" returnType="void">
</method>
</factory>
</type>
1.若传入参数为类,则实例属性嵌套在名为 <factory> 的标签内,从而与静态属性区分开来。在这种情况下,<type> 标签的 isStatic 属性为 true。
2.所有的非静态方法将显示在<factory> 标签内,静态方法显示在<factory> 标签外。
下表描述了由 describeType()
生成的 XML 对象的某些标签和属性(返回的所有类和接口名称均采用完全限定的格式):
标签 | 属性 | 说明 |
---|---|---|
<type> |
XML 对象的根标签。 | |
name | ActionScript 对象的数据类型的名称。 | |
base | ActionScript 对象的定义类的直接超类。如果 ActionScript 对象是类对象,则值为 Class 。 |
|
isDynamic | 如果 ActionScript 对象的定义类是动态的,则为 true ;否则为 false 。如果 ActionScript 对象是类对象,则值为 true ,因为 Class 类是动态的。 |
|
isFinal | 如果 ActionScript 对象的定义类是最终类,则为 true ;否则为 false 。 |
|
isStatic | 如果 ActionScript 对象是类对象或构造函数,则为 true ;否则为 false 。此属性之所以名为 isStatic ,原因是:如果此属性为 true ,则未嵌套在 factory 标记内的任何标签都是静态的。 |
|
<extendsClass> |
ActionScript 对象的定义类的每个超类都有一个单独的 extendsClass 标签。 |
|
type | ActionScript 对象的定义类扩展的超类的名称。 | |
<implementsInterface> |
ActionScript 对象的定义类或其任何超类实现的每个接口都有一个单独的 implementsInterface 标签。 |
|
type | ActionScript 对象的定义类实现的接口的名称。 | |
<accessor> |
存取器是 getter 和 setter 函数定义的一个属性。 | |
name | 存取器的名称。 | |
access | 属性的访问权限。可能的值包括 readonly 、writeonly 和 readwrite 。 |
|
type | 属性的数据类型。 | |
declaredBy | 包含关联的 getter 或 setter 函数的类。 | |
<constant> |
常量是用 const 语句定义的一个属性。 |
|
name | 常量的名称。 | |
type | 常量的数据类型。 | |
<constructor> |
在构造函数有参数时显示。 | |
<method> |
方法是作为类定义的一部分声明的函数。 | |
name | 方法的名称。 | |
declaredBy | 包含方法定义的类。 | |
returnType | 方法的返回值的数据类型。 | |
<parameter> |
方法定义的每个参数都有一个单独的 parameter 标签。此标签始终嵌套在 <method> 标签内。 |
|
index | 一个数字,对应于参数在方法的参数列表中出现的顺序。第一个参数的值为 1。 | |
type | 参数的数据类型。 | |
optional | 如果参数是可选参数,则为 true ;否则为 false 。 |
|
<variable> |
变量是用 var 语句定义的一个属性。 |
|
name | 变量的名称。 | |
type | 变量的数据类型。 | |
<factory> |
如果 ActionScript 对象是类对象或构造函数,则所有实例属性和方法均嵌套在此标签内。如果 <type> 标签的 isStatic 属性为 true ,则未嵌套在 <factory> 标签内的所有属性和方法都是静态的。只有在 ActionScript 对象是类对象或构造函数时,此标签才会出现。 |
|
<metadata> |
用[]括起来的标签 | |
name | 标签的名称。 | |
<arg> |
标签中()括起来的参数 | |
key | 参数的名称。 | |
value | 参数的值。 |
在debug编译条件下运行时我们能够正确获取metadata,但是release编译条件下会忽略未知的metadata,这时,需要在flex sdk的编译参数里面添加
-keep-as3-metadata+=MyMetadata
应用及API
1.定义依赖
Swiftsuspenders支持3种依赖定义:
a.值绑定,将一个注入请求返回为一个给定的对象
mapValue(whenAskedFor : Class, useValue : Object, named : String = "")
b.类绑定,将一个注入请求返回为一个给定类的新建的实例
mapClass(whenAskedFor : Class, instantiateClass : Class, named : String = "")
c.单例绑定,将所有的注入请求返回为同一个共享的实例,这个实例由第一次请求时创建。
mapSingleton(whenAskedFor : Class, named : String = "")
public function mapSingletonOf(whenAskedFor : Class, useSingletonOf : Class, named : String = "")
另外,Swiftsuspenders支持通过使用mapRule来扩展依赖映射
当一个类型在多处被注入,且需要使用不同的注入依赖时,通过指定注入名的方式来区别各处的注入。
2.定义注入点
Swiftsuspenders支持在4个位置进行注入:
a.属性(如setter)
b.变量
c.方法(支持可选参数)
d.构造函数(支持可选参数)
3.变量注入的用例
public interface IClass
{
function ClassInfo():String;
} public class ClassA implements IClass
{ public function ClassA()
{ }
public function ClassInfo():String
{
return "Class A";
}
} public class ClassB implements IClass
{ public function ClassB()
{ }
public function ClassInfo():String
{
return "Class B";
}
} public class MyClass
{
[Inject]
public var iclass:IClass; public function MyClass()
{ }
public function TraceOut():void
{
trace(iclass.ClassInfo());
} } var inj :Injector = new Injector(); inj.mapClass(MyClass, MyClass);
inj.mapClass(IClass, ClassA);
var a:MyClass = inj.getInstance(MyClass);
inj.unmap(IClass);
inj.mapClass(IClass, ClassB);
var b:MyClass = inj.getInstance(MyClass);
a.TraceOut();
b.TraceOut();
4.构造函数注入的用例
当对构造函数注入使用注入名时,元数据必须放在类定义的前面,而不是在构造函数前,这个是由于Flash Player的限制造成的。
只需修改上面代码中的MyClass类:
[Inject]
public class MyClass
{
public var iclass:IClass; public function MyClass(c:IClass)
{
iclass = c;
}
public function TraceOut():void
{
trace(iclass.ClassInfo());
} }
5.其他
a.可以使用PostConstruct来标注注入完成后自动调用的方法
有些需要在注入完成后调用的方法,可以申明[PostConstruct]元数据,从而在所有的注入完成后,自动调用被[PostConstruct]申明的方法。可以通过order参数来决定方法调用的顺序,如:
[PostConstruct(order=1)]
b.可以用hasMapping来查询某依赖是否已经存在,若是需要重新映射已经存在的依赖,需要先使用unmap方法解除原有依赖。
c.支持子注入器,通过createChildInjector方法实现。
d.支持通过XML文件配置注入信息。
设计结构
SwiftSuspenders的类图如上图所示。整个框架以Injector为核心。InjectionPoint包中包含了所有与注入点相关的类,InjectionResult包中包含了返回策略相关的类。
Injector中的m_mappings中包含所有的映射关系InjectionConfig,当调用mapClass,mapValue,mapSingleton时实际上就是建立类的映射关系,其序列图如下:
m_injecteeDescriptions中包含InjecteeDescription对象,这个对象包括所有的注入点信息,包括构造注入点信息,和其他注入点信息。当getInstance时将根据之前配置的映射信息来获取所有注入点,再通过根据注入点进行注入来获取最终的对象,其流程图如下:
这里面getInjectionPoints函数就是利用之前介绍的describeType函数来获取类的内容,并进行解析以获取注入点。
轻量级IOC框架SwiftSuspenders的更多相关文章
- 轻量级IOC框架Guice
java轻量级IOC框架Guice Guice是由Google大牛Bob lee开发的一款绝对轻量级的java IoC容器.其优势在于: 速度快,号称比spring快100倍. 无外部配置(如需要使用 ...
- 轻量级IOC框架:Ninject
Ninject 学习杂记 - liucy 时间2014-03-08 00:26:00 博客园-所有随笔区原文 http://www.cnblogs.com/liucy1898/p/3587455.h ...
- 轻量级IOC框架:Ninject (上)
前言 前段时间看Mvc最佳实践时,认识了一个轻量级的IOC框架:Ninject.通过google搜索发现它是一个开源项目,最新源代码地址是:http://github.com/enkari/ninje ...
- java轻量级IOC框架Guice(转)
出处:http://www.cnblogs.com/whitewolf/p/4185908.html Guice是由Google大牛Bob lee开发的一款绝对轻量级的java IoC容器.其优势在于 ...
- 轻量级IoC框架Ninject.NET搭建
说在之前的话 IOC的概念相信大家比较熟悉了,习惯性称之为依赖注入或控制反转,园子里对基于MVC平台IOC设计模式已经相当多了,但大家都只知道应该怎么应用一个IOC模式,比如Ninject, Unit ...
- java轻量级IOC框架Guice
Google-Guice入门介绍(较为清晰的说明了流程):http://blog.csdn.net/derekjiang/article/details/7231490 使用Guice,需要添加第三方 ...
- 轻量级IOC框架:Ninject (下)
一,创建依赖链(Chains of Dependency) 当我们向Ninject请求创建一个类型时,Ninject会去检查该类型和其他类型之间的耦合关系.如果有额外的依赖,Ninject也会解析它们 ...
- 使用Microsoft的IoC框架:Unity来对.NET应用进行解耦
1.IoC/DI简介 IoC 即 Inversion of Control,DI 即 Dependency Injection,前一个中文含义为控制反转,后一个译为依赖注入,可以理解成一种编程模式,详 ...
- IOC框架
一. IOC理论的背景 我们都知道,在采用面向对象方法设计的软件系统中,它的底层实现都是由N个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑. 图1:软件系统中耦合的对象 如果我们打开机 ...
随机推荐
- hdu A Bug's Life
题目意思:给定一系列数对,例如a和b,表示a和b不是同一种性别,然后不断的给出这样的数对,问有没有性别不对的情况. 例如给定: 1 2 3 4 1 3 那这里就是说1和2不是同种性别 ...
- static静态结合&符号理解
上代码,方法定义为静态变量 <?php function &test(){ static $c=222; return $c; } $a=&test(); echo $a; ec ...
- Linux下动态库(.so)和静态库(.a) 的区别
静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库.编译之后程序文件大,但加载快,隔离性也好.动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还 ...
- 【iCore3 双核心板】例程九:ADC实验——电源监控
实验指导书及代码包下载: http://pan.baidu.com/s/1o7wSEO6 iCore3 购买链接: https://item.taobao.com/item.htm?id=524229 ...
- C输入输出函数与缓冲区
#转 对C语言输入输出流和缓冲区的深入理解C语言缓冲区(缓存)详解缓冲区又称为缓存,它是内存空间的一部分.也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的 ...
- AFNetworking 3.0 版本使用
原创:http://www.zhimengzhe.com/IOSkaifa/38653.html AFNetworking 3.0 版本使用 在Xcode7.0之后,苹果废弃了NSURLConnect ...
- C# DataGrid合并单元格
1.栏位枚举 private enum DataGridColumn { ROWNUM = , EMPID, EMPNAME, SEX, SALARY, ADRRESS, PHONE, TEL, PO ...
- MySQL中文全文检索
一.概述 MySQL全文检索是利用查询关键字和查询列内容之间的相关度进行检索,可以利用全文索引来提高匹配的速度. 二.语法 MATCH (col1,col2,...) AGAINS ...
- ubuntu dpkg 依赖问题处理
ubuntu dpkg 依赖问题处理 使用 apt-get 安装软件期间,如果出现意外中断的情况,下次安装时会出现 dpkg 的一系列依赖问题,提示如下 :: dpkg: error processi ...
- 去除行内(inline/inline-block)元素之间的间距
先展示一下,行内元素之间存在间距,实例代码如下: <style> div { color: #fff; padding: 25px 50px; } .inline-f00 { displa ...