Spring.NET教程(五)容器中物件的作用域(基礎篇)
容器中物件的部署分為兩種方式:singleton和非singleton(Java裡叫prototype)。這裡的singleton指的是“單例模式”,就是說當一個物件被定義為singleton時,容器中就只會有一個共享的例項,任何時候通過id或別名請求該物件都會返回這個共享例項的引用(也就是說這個物件只會被建立一次)。當使用非singleton,或者說原型模式佈署時,每次請求物件都會建立新的例項。在某些場合,如果需要為每個使用者返回單獨的使用者物件或其它物件,非singlton佈署模式就比較理想。Spring.net預設為singleton模式。每次呼叫GetObject方法時得到的都是同樣的例項;當singleton="false"時,每次呼叫GetObject方法時得到的則是不同的例項。
<!--單例模式-->
<object id="personDao" type="SpringNetScop.PersonDao, SpringNetScop" />
CreateWithSingleton
[Test]
public void CreateWithSingleton()
{
string[] XMLFiles = new string[]
{
"assembly://SpringNetScop/SpringNetScop/Objects.XML"
};
IApplicationContext context = new XmlApplicationContext(xmlFiles);
IObjectFactory factory = (IObjectFactory)context;
object obj1 = factory.GetObject("personDao");
object obj2 = factory.GetObject("personDao");
Assert.AreEqual(obj1, obj2);
}
我們用NUnit可以看到下圖:
使用singleton="false"的程式碼
<!--非單例模式-->
<object id="person" type="SpringNetScop.Person, SpringNetScop" singleton="false" />
CreateWithOutSingleton
[Test]
public void CreateWithOutSingleton()
{
string[] XMLFiles = new string[]
{
"assembly://SpringNetScop/SpringNetScop/Objects.XML"
};
IApplicationContext context = new XmlApplicationContext(xmlFiles);
IObjectFactory factory = (IObjectFactory)context;
object obj1 = factory.GetObject("person");
object obj2 = factory.GetObject("person");
Assert.AreNotEqual(obj1, obj2);
}
Person
public class Person
{
public Person()
{
Console.WriteLine("Person被例項");
}
public override string ToString()
{
return "我是Person";
}
~Person()
{
Console.WriteLine("Person被銷燬");
圖為:
這說明singleton=false後,每次呼叫GetObject方法獲取的物件是不同例項的,當脫離呼叫方法(CreateWithOutSingleton)的作用域後,該例項會被Spring.net容器銷燬。
lazy-init屬性是指:當Spring.NET容器初始化的時候標註該屬性的物件將被例項化,反之則是呼叫GetObject方法的時候才被例項化。
<!--呼叫時載入-->
<object id="personServer" type="SpringNetScop.PersonServer, SpringNetScop" lazy-init="true" />
CreateWithLazy
[Test]
public void CreateWithLazy()
{
string[] XMLFiles = new string[]
{
"assembly://SpringNetScop/SpringNetScop/Objects.XML"
};
IApplicationContext context = new XmlApplicationContext(xmlFiles);
IObjectFactory factory = (IObjectFactory)context;
object dao = factory.GetObject("personDao");
Console.WriteLine(dao.ToString());
object server = factory.GetObject("personServer");
Console.WriteLine(server.ToString());
}
PersonServer
public class PersonServer
{
public PersonServer()
{
Console.WriteLine("PersonServer被例項");
}
public override string ToString()
{
return "我是PersonServer";
}
}
如圖:
PersonDao類未設定lazy-init屬性,則當Spring.NET初始化時被例項;PersonServer類設定lazy-init="true",則當呼叫GetObject方法時才被例項。
一般情況下可以有選擇的設定lazy-init屬性,正如雙刃劍一樣,設定為lazy-init=true的時候應用程式啟動時會快一點,但是在啟動的時候就不能夠幫我們檢測錯誤,但當呼叫的時候一旦發生錯誤,後果是不堪設想的。
更多資料請檢視Spring.NET中文手冊。