Spring容器中Bean的作用域之singleton和prototype

来源:互联网 发布:淘宝推广方式 编辑:程序博客网 时间:2024/05/22 10:47

当通过Spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域。Spring支持如下5种作用域,在这里主要说的就是大名鼎鼎的singleton–单例模式和prototype–原型模式,这两个Bean的作用域也是在Spring中比较常见的。其中关于单例模式的概念为我的博客中有写到,可以出门右转去找找,这里在不赘述。
一、singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例;注意这里的Spring singleton模式是默认缺省的饿汉模式,启容器时(即实例化容器时),为所有spring配置文件中定义的bean都生成一个实例。
核心代码如下:

class Bean {        private static final Bean theBean;        private Bean() {}          public static Bean getBean() {            return theBean;        }   }

可是这样做会导致系统的开销比较大,为了不占用过大的资源或者是减少开销,一般我会在spring中添加缺省文件:

<beans default-lazy-init="true">

将系统默认的饿汉模式转换成懒汉模式,也就是在第一次请求的时候我们才生成一个实例,在之后的使用中继续调用即可
核心代码如下:

class Bean {        private static final Bean theBean;        private Bean() {}          public static Bean getBean() {            if (theBean == null) {                theBean = new Bean();            }            return theBean;        }   }

二、prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例。
对于singleton作用域的 Bean,每次请求该Bean都将获得相同的实例。容器负责跟踪Bean实例的状态,负责维护Bean实例的生命周期行为;如果一个Bean被设置成 prototype作用域,程序每次请求该id的Bean,Spring都会新建一个Bean实例,然后返回给程序。在这种情况下,Spring容器仅仅 使用new 关键字创建Bean实例,一旦创建成功,容器不在跟踪实例,也不会维护Bean实例的状态。
如果不指定Bean的作用域,Spring默认使用singleton作用域。Java在创建Java实例时,需要进行内存申请;销毁实例时,需要完成垃圾回收,这些工作都会导致系统开销的增加。因此,prototype作用域Bean的创建、销毁代价比较大。而singleton作用域的Bean实例一旦创建成功,可以重复使用。因此,除非必要,否则尽量避免将Bean被设置成prototype作用域。
测试代码:

<!-- 默认的作用域:singleton --><bean id="p1" class="com.cxg.User" /> <!-- 指定的作用域:prototype --><bean id="p2" class="com.cxg.User" scope="prototype" />
public class BeanTest {  public static void main(String args[]) {    //加载类路径下的beans.xml文件以初始化Spring容器    ApplicationContext context = new ClassPathXmlApplicationContext();    //分两次分别取同一个Bean,比较二者是否是同一个对象    System.out.println(context.getBean("p1") == context.getBean("p1"));    System.out.println(context.getBean("p2") == context.getBean("p2"));  }}

执行结果:

truefalse

从结果可以看出,正如上文所述:对于singleton作用域的Bean,每次请求该id的Bean,都将返回同一个实例,而prototype作用域的Bean, 每次请求都将产生全新的实例。
注意:早期指定Bean的作用域也可通过singleton属性指定,该属性只接受两个属性值:true和false,分别代表singleton和prototype的作用域。使用singleton属性则无法指定其他三个作用域。实际上Spring2.X不推荐使用singleton属性指定Bean的作用域,singleton属性是Spring 1.2.X的使用方式。

0 0
原创粉丝点击