首页 > 代码库 > 认识Robotlegs(一)注入过程的分析
认识Robotlegs(一)注入过程的分析
提到Robotlegs,很多人都读过一篇叫做《Robotlegs最佳实践》的教程,都知道Robotlegs是一个基于IOC的MVC微框架,其内部的注入机制有三种绑定规则(值绑定、类绑定、 单例绑定),现在我以SwiftSuspenders的视角再来分析一下注入的实现过程。
SwiftSuspenders实现注入的过程大致是下面的步骤:
1)创建注入器
2)添加注入规则
3)初始化注入宿主(InjecteeClass)
4)对注入宿主进行注入 (把注入对象注入到宿主内部)
1 /**注入对象*/ 2 package 3 { 4 public class InjectObject 5 { 6 public function InjectObject() 7 { 8 trace("InjectObject Created"); 9 } 10 public function call():void 11 { 12 trace("InjectObject Called"); 13 } 14 } 15 } 16 17 18 /**注入宿主*/ 19 package 20 { 21 public class InjecteeClass 22 { 23 [Inject] 24 public var injectPoint:InjectObject; 25 public function InjecteeClass() 26 { 27 trace("InjecteeClass Created"); 28 //injectPoint.call(); 29 } 30 [PostConstruct(order=1)] 31 public function order1():void 32 { 33 trace("InjecteeClass PostConstruct"); 34 injectPoint.call(); 35 } 36 } 37 } 38 39 40 /**程序*/ 41 package 42 { 43 import flash.display.Sprite; 44 import org.swiftsuspenders.Injector; 45 public class InjectorTest extends Sprite 46 { 47 public function InjectorTest() 48 { 49 var injector:Injector = new Injector(); 50 injector.mapClass(InjectObject, InjectObject); 51 52 /**方式1*/ 53 var instance:InjecteeClass = new InjecteeClass(); 54 injector.injectInto(instance); 55 56 /**方式2*/ 57 injector.mapClass(InjecteeClass, InjecteeClass); 58 var instance:InjecteeClass = injector.getInstance(InjecteeClass); 59 60 /**方式3*/ 61 var instance:InjecteeClass = injector.instantiate(InjecteeClass); 62 } 63 } 64 }
输出
--------------------------------------------
InjecteeClass Created
InjectObject Created
InjecteeClass PostConstruct
InjectObject Called
代码分析 var injector:Injector = new Injector(); 创建注入器 (过程1)
injector.mapClass(InjectObject, InjectObject); 为注入器增加注入规则(过程2) 此处增加的注入规则是:在需要InjectObject的地方创建一个新的InjectObject实例并注入。
[Inject] public var injectPoint:InjectObject; 此处需要注入InjectObject,根据注入器的注入规则会创建一个新的InjectObject实例并注入到injectPoint类变量。(过程4) 实际上实现过程4需要调用注入器的injectInto方法,只有在调用了注入器的injectInto方法时才会真正进行注入。
在完成过程4之前还需要初始化注入宿主类(过程3) 注入宿主类是指内部有注入需求的类。注入分为类属性注入和类构造注入,这里只讨论类属性注入的情况。 类属性即类变量,需要public访问控制符,因为注入是从类外部进行的,所以只有那些public属性才能接收注入。 SwiftSuspenders 提供的初始化宿主类并实现注入的写法有三种,对应有如下代码(任用一种即可):
/**方式1*/ var instance:InjecteeClass = new InjecteeClass(); injector.injectInto(instance); /**方式2*/ injector.mapClass(InjecteeClass, InjecteeClass); var instance:InjecteeClass = injector.getInstance(InjecteeClass); /**方式3*/ var instance:InjecteeClass = injector.instantiate(InjecteeClass);
方式1最清晰,先实例化宿主类InjecteeClass,然后用注入器的injectInto方法按规则将对象注入到InjecteeClass内部。 没有injectInto将不会有注入的行为,也就是说示例中InjecteeClass的injectPoint属性为null。
方式2实现注入和方式1有所不同,但是结果是一样的。 首先要做的是实例化InjecteeClass,这里没有直接实例化,而是通过注入规则实现实例化。
injector.mapClass(InjecteeClass, InjecteeClass)设定了注入规则,当需要InjecteeClass的时候创建一个新的InjecteeClass对象。 injector.getInstance(InjecteeClass)这句实现按注入规则获得一个InjecteeClass对象实例,并对该实例进行injectInto操作。 所以方式2和方式1是一样的流程,不同的是方式2为InjecteeClass也创建了注入规则。
方式3可以看作方式2的简化写法, injector.instantiate()会自动创建注入规则(mapClass)并完成注入(injectInto)。
上面提到完成注入需要的过程有4步:创建注入器、添加注入规则、初始化注入宿主、对宿主进行注入。
如果在宿主类InjecteeClass的构造方法中访问injectPoint只会得到一个空值,因为真正的注入尚未完成。
那么怎样才能在宿主类InjecteeClass构造完成后马上访问injectPoint呢?答案是可以的,SwiftSuspenders 会在注入完成后立即调用带有[PostConstruct(order=1)]标签的方法(如果有多个,按order序号顺序调用),在这个方法中就可以访问injectPoint。
最后总结一下,整个注入的详细流程是这样的:
1)创建一个注入器Injector对象。
2)为Injector添加注入规则
3)初始化宿主类InjecteeClass
4)对InjecteeClass进行injectInto
5)遍历InjecteeClass内部带有[Inject]标签的类属性,查找注入规则获取注入对象实例并赋值给该属性。
6)调用带有[PostConstruct]的类方法
其中5和6是injectInto之后SwiftSuspenders自动完成的。
KevinChu
2014/6/6