首页 > 代码库 > 认识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