天天看點

Spring使用靜态工廠方法建立Bean

1. 使用靜态工廠方法建立bean

    使用靜态工廠方法建立bean執行個體時,class屬性也必須指定,但此時class屬性并不是指定bean執行個體的實作類,而是靜态工廠類。因為spring需要知道是用哪個工廠來建立bean執行個體。另外,還需要使用factory-method來指定靜态工廠方法名,spring将調用靜态工廠方法(可能包含一組參數),來傳回一個bean執行個體,一旦獲得了指定bean執行個體,spring後面的處理步驟與采用普通方法建立bean執行個體則完全一樣。需要注意的是,當使用靜态工廠方法來建立bean時,這個factory-method必須要是靜态的。這段闡述聽上去有點暈,話不多說,上代碼:

    先定義一個接口,靜态方法産生的将是該接口的執行個體:

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

1

2

3

<code>public</code> <code>interface</code> <code>animal {</code>

<code>    </code><code>public</code> <code>void</code> <code>sayhello();</code>

<code>}</code>

    下面是接口的兩個實作類:

4

5

6

7

8

9

10

11

<code>public</code> <code>class</code> <code>cat </code><code>implements</code> <code>animal {</code>

<code>    </code><code>private</code> <code>string msg;</code>

<code>    </code><code>//依賴注入時必須的setter方法</code>

<code>    </code><code>public</code> <code>void</code> <code>setmsg(string msg){</code>

<code>        </code><code>this</code><code>.msg = msg;</code>

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

<code>    </code><code>@override</code>

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

<code>        </code><code>system.out.println(msg + </code><code>",喵~喵~"</code><code>);</code>

<code>public</code> <code>class</code> <code>dog </code><code>implements</code> <code>animal {</code>

<code>        </code><code>system.out.println(msg + </code><code>",旺~旺~"</code><code>);</code>

    下面的animalfactory工廠中包含了一個getanimal的靜态方法,該方法将根據傳入的參數決定建立哪個對象。這是典型的靜态工廠設計模式。

<code>public</code> <code>clas animalfactory {</code>

<code>    </code><code>public</code> <code>static</code> <code>animal getanimal(string type){</code>

<code>        </code><code>if</code> <code>(</code><code>"cat"</code><code>.equalsignorecase(type)){</code>

<code>            </code><code>return</code> <code>new</code> <code>cat();</code>

<code>        </code><code>} </code><code>else</code> <code>{</code>

<code>            </code><code>return</code> <code>new</code> <code>dog();</code>

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

    如果需要指定spring使用animalfactory來産生animal對象,則可在spring配置檔案中作如下配置:

12

13

14

<code>&lt;!-- 配置animalfactory的getanimal方法,使之産生cat --&gt;</code>

<code>&lt;</code><code>bean</code> <code>id</code><code>=</code><code>"cat"</code> <code>class</code><code>=</code><code>"com.abc.animalfactory"</code> <code>factory-method</code><code>=</code><code>"getanimal"</code><code>&gt;</code>

<code>    </code><code>&lt;!-- 配置靜态工廠方法的參數,getanimal方法将産生cat類型的對象 --&gt;</code>

<code>    </code><code>&lt;</code><code>constructor-arg</code> <code>value</code><code>=</code><code>"cat"</code> <code>/&gt;</code>

<code>    </code><code>&lt;!-- 通過setter注入的普通屬性 --&gt;</code>

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

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

<code>&lt;!-- 配置animalfactory的getanimal方法,使之産生dog --&gt;</code>

<code>&lt;</code><code>bean</code> <code>id</code><code>=</code><code>"dog"</code> <code>class</code><code>=</code><code>"com.abc.animalfactory"</code> <code>factory-method</code><code>=</code><code>"getanimal"</code><code>&gt;</code>

<code>    </code><code>&lt;!-- 配置靜态工廠方法的參數,getanimal方法将産生dog類型的對象 --&gt;</code>

<code>    </code><code>&lt;</code><code>constructor-arg</code> <code>value</code><code>=</code><code>"dog"</code> <code>/&gt;</code>

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

    從上面的配置可以看出:cat和dog兩個bean配置的class和factory-method完全相同,這是因為兩個執行個體都使用同一個靜态工廠類、同一個靜态工廠方法産生得到的。隻是為這個靜态工廠方法指定的參數不同,使用&lt;constructor-arg /&gt;元素來為靜态工廠方法指定參數。

    主程式擷取cat和dog兩個bean執行個體的方法不變,同樣隻需要調用spring容器的getbean()即可:

<code>public</code> <code>class</code> <code>test {</code>

<code>    </code><code>public</code> <code>static</code> <code>void</code> <code>main(string args[]){</code>

<code>        </code><code>applicationcontext context = </code>

<code>                </code><code>new</code> <code>classpathxmlapplicationcontext(</code><code>"applicationcontext.xml"</code><code>);</code>

<code>        </code><code>animal a1 = context.getbean(</code><code>"cat"</code><code>, animal.</code><code>class</code><code>);</code>

<code>        </code><code>a1.sayhello();</code>

<code>        </code><code>animal a2 = context.getbean(</code><code>"dog"</code><code>, animal.</code><code>class</code><code>);</code>

<code>        </code><code>a2.sayhello();</code>

    輸出結果:

<code>貓貓,喵~喵~</code>

<code>狗狗,旺~旺~</code>

    使用靜态工廠方法建立執行個體時必須提供工廠類和産生執行個體的靜态工廠方法。通過靜态工廠方法建立執行個體時需要對spring配置檔案做如下改變;

class屬性不在是bean執行個體的實作類,而是生成bean執行個體的靜态工廠類

使用factory-method指定生産bean執行個體的靜态工廠方法

如果靜态工廠方法需要參數,使用&lt;constructor-arg /&gt;元素為其配置

    當我們指定spring使用靜态工廠方法來建立bean執行個體時,spring将先解析配置檔案,并根據配置檔案指定的資訊,通過反射調用靜态工廠類的靜态工廠方法,并将該靜态工廠方法的傳回值作為bean執行個體,在這個過程中,spring不再負責建立bean執行個體,bean執行個體是由使用者提供的靜态工廠方法提供的。

2. 使用執行個體工廠方法建立bean

    執行個體工廠方法與靜态工廠方法隻有一點不同:調用靜态工廠方法隻需要使用工廠類即可,調用執行個體工廠方法則必須使用工廠執行個體。是以在spring配置上也隻有一點差別:配置靜态工廠方法指定靜态工廠類,配置執行個體工廠方法則指定工廠執行個體。同樣是上面的例子将animalfactory修改為:

<code>    </code><code>public</code> <code>animal getanimal(string type){  </code><code>//這裡僅僅是去掉了static關鍵字</code>

    spring檔案修改為:

<code>&lt;!-- 先配置工廠類 --&gt;</code>

<code>&lt;</code><code>bean</code> <code>id</code><code>=</code><code>"animalfactory"</code> <code>class</code><code>=</code><code>"com.abc.animalfactory"</code> <code>/&gt;</code>

<code>&lt;!-- 這裡使用factory-bean指定執行個體工廠類對象 --&gt;</code>

<code>&lt;</code><code>bean</code> <code>id</code><code>=</code><code>"cat"</code> <code>factory-bean</code><code>=</code><code>"animalfactory"</code> <code>factory-method</code><code>=</code><code>"getanimal"</code><code>&gt;</code>

<code>    </code><code>&lt;!-- 同樣指定factory-method的參數 --&gt;</code>

<code>&lt;</code><code>bean</code> <code>id</code><code>=</code><code>"dog"</code> <code>factory-bean</code><code>=</code><code>"animalfactory"</code> <code>factory-method</code><code>=</code><code>"getanimal"</code><code>&gt;</code>

    測試類不用修改,輸出結果和上面相同。