(殘夢追月原創,轉載請註明,原載與我的blogjava博客)
http://www.blogjava.net/cmzy/archive/2008/07/21/216415.html
在jsp中,使用jsp標籤來引用JavaBean,可以通過其scope屬性的值來確定該標籤引用JavaBean的作用範圍。在Spring IOC容器中,由它管理的Java Bean也具有作用範圍。
在Spring1.x版本中,標籤有一個屬性singleton,取值爲布爾類型。如果將其設置爲true,那麼容器之中只存在一個該bean的共享實例,當其他的任何Bean依賴該bean時,只要請求的id與該bean的id相同,容器就將該bean的實例注入到請求的bean中。換言之,Spring IoC容器只是創建該bean的一個唯一實例,並把它存存貯在容器的單例緩存中,在需要時纔將其取出。這樣的受管bean稱之爲“單例bean”。如果設置爲false,那麼每當其他bean依賴此bean時,容器則會重新實例化一個該bean對象,爲其注入。
需要注意的是:1、在下面的例子中,如果把computer1和computer2兩個受管bean都設置成單例bean,Spring IoC容器則分別實例化兩個bean,把它們作爲兩個不同的bean對待,儘管他們的類相同。
2 <bean id="computer2"class="ioc.test.Computer" scope="singleton"/></bean>
2、一般來說,對於無狀態的bean使用單例模式,對於有狀態的bean使用prototype模式。
3、Spring IoC容器不會維護prototype類型的bean的整個聲明週期,容器在實例化、配置、注入之後就把它扔給調用者,然後就不管了。
4、如果一個單例bean computer引用了一個prototype類型的bean host,由於單例bean只初始化一次,所以不能保證每次調用computer時host都是最新的。解決辦法是使用lookup方法注入。
到了Spring2.0時代,scope屬性代替了原來的的singleton屬性,scope提供了更多的選項,從而可以更加靈活的配置bean的作用範圍。Spring2.0中,scope屬性有如下可能的取值,說明如下:1、 singleton,即單例bean,和1.x中singleton=”true”相同。
2、 prototype,同Spring1.x中的singleton=”false”。
3、 request,這種bean在web的request範圍內有效,即每次請求時都會產生一個實例。只用於web程序中。4、 session,這種bean在web的session範圍內有效。只用於web程序中。
5、 global session,這種bean在web的全局session範圍內有效。只用於web portlet框架中。
下面通過一個例子來說明單例bean和prototype bean的使用。在例子中,我們創建一個DateTime類,在其構造方法中獲取當前的系統時間,並存貯於date成員之中。然後利用該類定義兩個bean,一個爲單例bean,一個爲prototype bean。利用線程,兩次調用getBean方法從IoC容器中獲取這兩個bean的實例,並將存儲於其中時間打印出來。爲了便於測試,在兩次調用getBean方法之間讓線程暫停小段時間。這樣,如果是單例bean,由於在容器中只是實例化一次,那麼兩次調用顯示的時間應當相同,prototype則不一樣。通過其返回時間是否一支來查看受管bean是否重新被實例化。
1、 新建一個java工程,爲添加Spring開發能力後,建一個包ioc.test。
2、創建一個類DateTime,添加一Date類型的成員,並添加Geter方法。修改其構造方法,讓其在構造方法中獲取當前系統時間,並存貯與date屬性中。代碼如下:
2
3 import java.util.Calendar;
4 import java.util.Date;
5
6 public class DateTime {
7 private Date date;
8 DateTime(){
9 this.date = Calendar.getInstance().getTime();
10 }
11 public Date getDate() {
12 return date;
13 }
14 }
15
3、新建一Thread類的子類MyThread,重載run方法,在run方法中兩次調用getBean方法從容器獲取bean實例,然後分別將存貯與bean實例中的時間打印出來。代碼如下:
2 import org.springframework.context.ApplicationContext;
3 public class MyThread extends Thread {
4
5 private ApplicationContext ac;
6 private DateTime dt;
7 private String bean;
8 MyThread(ApplicationContext ac,String bean){
9 this.ac=ac;
10 this.bean=bean;
11 }
12
13 @Override
14 public void run() {
15 //第一次從容器取得bean
16 dt = (DateTime) ac.getBean(bean);
17 System.out.println("Thread Id:" + this.getId()+" 時間:"+dt.getDate());
18
19 //線程暫停5秒
20 try {
21 sleep(1000 * 5);
22 } catch (InterruptedException e) {
23 }
24 //第二次從容器取得bean
25 dt = (DateTime) ac.getBean(bean);
26 System.out.println("Thread Id:" + this.getId()+" 時間:"+dt.getDate()); }
27 }
28
4、編寫Spring配置文件,配置兩個bean,一個singleton,一個prototype,如下:
2<beans ……>
3<bean id="singletonDateTime" class="ioc.test.DateTime" scope="singleton">bean>
4<bean id="prototypeDateTime" class="ioc.test.DateTime" scope="prototype">bean>
5beans>
6
5、編寫一測試類TestMain,代碼如下:
2
3 import org.springframework.context.ApplicationContext;
4 import org.springframework.context.support.ClassPathXmlApplicationContext;
5
6 public class TestMain {
7 public static void main(String[] args) {
8 ApplicationContext ac = new ClassPathXmlApplicationContext(
9 "applicationContext.xml");
10 //測試單例bean
11 MyThread mt1 = new MyThread(ac,"singletonDateTime");
12 mt1.start();
13
14 //測試prototype bean
15 MyThread mt2 = new MyThread(ac,"prototypeDateTime");
16 mt2.start();
17 }
18 }
19
6、運行測試類,結果如下:
By:殘夢追月