(残梦追月原创,转载请注明,原载与我的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,如下:
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
2
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
3
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
4
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
5
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
6
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
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、运行测试类,结果如下:
![](https://i-blog.csdnimg.cn/blog_migrate/851c3eb8f6f7122f1c9a473e528d25e5.jpeg)
By:残梦追月