天天看點

類Spring IoC容器

在建構tiny架構之初,想着是不是不要強依賴spring?于是就寫了一個類spring的依賴注入容器,基本實作了spring的依賴注入部分的功能,工作情況也良好,配置規範也是采用的spring的規範。在前面一直是沒有問題的,但是在做資料庫業務的時候,出現問題了。做資料庫,必須要考慮事務問題,而當時我的設計目标是對各種開源的ormapping方案都不拒絕,這個時候就引入一個問題,要麼自己再實作一套aop,要麼就複用spring。當時預想的另外一個方案是核心架構采用非直接依賴spring的方案,資料庫相關的采用spring依賴的方式。但是實際上,業務層面的bean會依賴系統層面的bean,這又涉及到兩個容器之間的協作,這個時候,我意識到,是應該做一個取舍了。

是以果斷放棄自己來做ioc和aop方面的工作,而采用強依賴spring來實作的方案,畢竟在現在的應用場景下,拒絕spring就等于讓别人拒絕自己。

但是,不管怎麼樣,在實作這個容器的過程中,還是讓我對依賴注入方面有了更深的了解,是以,這兩天的投入還是值得的。

下面展示一下,它實作的功能:

<a href="http://my.oschina.net/tinyframework/blog/170763#">?</a>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

<code>&lt;beans&gt;</code>

<code>    </code><code>&lt;bean id=</code><code>"user"</code> <code>name=</code><code>"user,user1,user2"</code> <code>scope=</code><code>"singleton"</code>

<code>        </code><code>class</code><code>=</code><code>"org.tinygroup.factory.config.user"</code><code>&gt;</code>

<code>        </code><code>&lt;property name=</code><code>"name"</code><code>&gt;</code>

<code>            </code><code>&lt;value&gt;aa&lt;/value&gt;</code>

<code>        </code><code>&lt;/property&gt;</code>

<code>        </code><code>&lt;property name=</code><code>"age"</code><code>&gt;</code>

<code>            </code><code>&lt;value&gt;</code><code>12</code><code>&lt;/value&gt;</code>

<code>        </code><code>&lt;property name=</code><code>"cat"</code><code>&gt;</code>

<code>            </code><code>&lt;ref id=</code><code>"cat"</code> <code>/&gt;</code>

<code>        </code><code>&lt;property name=</code><code>"cats"</code><code>&gt;</code>

<code>            </code><code>&lt;list&gt;</code>

<code>                </code><code>&lt;ref id=</code><code>"cat"</code> <code>/&gt;</code>

<code>            </code><code>&lt;/list&gt;</code>

<code>        </code><code>&lt;property name=</code><code>"catset"</code><code>&gt;</code>

<code>        </code><code>&lt;property name=</code><code>"catmap"</code><code>&gt;</code>

<code>            </code><code>&lt;map&gt;</code>

<code>                </code><code>&lt;entry key=</code><code>"aa"</code> <code>value-ref=</code><code>"cat"</code><code>&gt;&lt;/entry&gt;</code>

<code>            </code><code>&lt;/map&gt;</code>

<code>    </code><code>&lt;/bean&gt;</code>

<code>    </code><code>&lt;bean id=</code><code>"cat"</code> <code>scope=</code><code>"singleton"</code> <code>class</code><code>=</code><code>"org.tinygroup.factory.config.cat"</code> <code>/&gt;</code>

<code>    </code><code>&lt;bean id=</code><code>"cat1"</code> <code>scope=</code><code>"prototype"</code> <code>class</code><code>=</code><code>"org.tinygroup.factory.config.cat"</code> <code>/&gt;</code>

<code>    </code><code>&lt;bean id=</code><code>"aaa1"</code> <code>scope=</code><code>"singleton"</code> <code>class</code><code>=</code><code>"org.tinygroup.factory.config.aaa"</code><code>&gt;</code>

<code>            </code><code>&lt;value&gt;aaa1&lt;/value&gt;</code>

<code>    </code><code>&lt;bean id=</code><code>"aaa"</code> <code>scope=</code><code>"singleton"</code> <code>class</code><code>=</code><code>"org.tinygroup.factory.config.aaa"</code><code>&gt;</code>

<code>            </code><code>&lt;value&gt;aaa&lt;/value&gt;</code>

<code>    </code><code>&lt;bean id=</code><code>"bbb"</code> <code>scope=</code><code>"singleton"</code> <code>class</code><code>=</code><code>"org.tinygroup.factory.config.bbb"</code>

<code>        </code><code>autowire=</code><code>"bytype"</code> <code>/&gt;</code>

<code>    </code><code>&lt;bean id=</code><code>"ccc"</code> <code>scope=</code><code>"singleton"</code> <code>class</code><code>=</code><code>"org.tinygroup.factory.config.ccc"</code>

<code>        </code><code>autowire=</code><code>"byname"</code> <code>/&gt;</code>

<code>    </code><code>&lt;bean id=</code><code>"user2"</code> <code>name=</code><code>"user,user1,user2"</code> <code>scope=</code><code>"prototype"</code>

<code>            </code><code>&lt;value&gt;aa1&lt;/value&gt;</code>

<code>            </code><code>&lt;value&gt;</code><code>121</code><code>&lt;/value&gt;</code>

<code>            </code><code>&lt;ref id=</code><code>"cat1"</code> <code>/&gt;</code>

<code>&lt;/beans&gt;</code>

可以看到,配置與spring是相容的。

下面是一些測試用例:

<code>&lt;span&gt;&lt;/span&gt;</code><code>public</code> <code>void</code> <code>testautoassemble() {</code>

<code> </code><code>assertnotnull(factory.getbean(</code><code>"aaa"</code><code>));</code>

<code> </code><code>bbb bbb = factory.getbean(</code><code>"bbb"</code><code>);</code>

<code> </code><code>assertequals(</code><code>"aaa"</code><code>, bbb.getaaa().getname());</code>

<code> </code><code>bbb = factory.getbean(</code><code>"bbb"</code><code>);</code>

<code> </code><code>ccc ccc = factory.getbean(</code><code>"ccc"</code><code>);</code>

<code> </code><code>assertequals(</code><code>"aaa1"</code><code>, ccc.getaaa1().getname());</code>

<code> </code><code>ccc = factory.getbean(</code><code>"ccc"</code><code>);</code>

<code> </code><code>}</code>

<code> </code><code>public</code> <code>void</code> <code>testinitcompareprototype() {</code>

<code> </code><code>cat cat = factory.getbean(</code><code>"cat1"</code><code>);</code>

<code> </code><code>cat cat1 = factory.getbean(</code><code>"cat1"</code><code>);</code>

<code> </code><code>assertequals(</code><code>false</code><code>, cat == cat1);</code>

<code> </code><code>public</code> <code>void</code> <code>testinitcompareprototype1() {</code>

<code> </code><code>user user = factory.getbean(</code><code>"user2"</code><code>);</code>

<code> </code><code>user user2 = factory.getbean(</code><code>"user2"</code><code>);</code>

<code> </code><code>assertequals(</code><code>false</code><code>, user == user2);</code>

<code> </code><code>assertequals(</code><code>false</code><code>, user.getcatmap() == user2.getcat());</code>

小結:确實,現在要脫離spring自己再實作一個容器,越來越不合适了,畢竟spring的使用者群在那裡,大家都已經熟悉适用的東西,不管是從學習成本各方面都不會選擇一個新東西。

ok,雖然是一個失敗的實踐,但是自己實作與看spring源碼的差别還是有的,就當是一次學習吧。當然,如果是在嵌入式系統或者受限制使用的環境中,隻想使用ioc,還是有用處的,畢竟 20k大小的容量還是相當誘人的。