提到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);
5960 /**方式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
认识Robotlegs(一)注入过程的分析,布布扣,bubuko.com