在Spring中Bean的作用域是可以自己定义的,如果你想每次需要bean时都产生一个新的bean实例时你可以声明Bean的作用域的属性值为prototype。
而在Spring中Bean的作用域属性默认为singleton,其实也就是单例的。
Spring 框架支持以下五个作用域,
作用域 | 描述 |
---|---|
singleton |
在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,默认值 |
prototype | 每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean() |
request | 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境 |
session | 同一个HTTP Session共享一个Bean,不同Session使用不同的Bean,仅适用于WebApplicationContext环境 |
global-session | 一般用于Portlet应用环境,该运用域仅适用于WebApplicationContext环境 |
本次就只讨论前两个作用域,当你使用web-aware ApplicationContext 的时候,剩余的三个也是可以使用的。
singleton作用域就是默认的作用域,当你创建Spring IOC的容器是时候,Bean对象无论是否使用,它也会随着Spring Ioc容器一起创建出来。
当你每次需要获取一个Bean对象的时候,获取的其实都是一个Bean对象。
创建一个简单的实体类,在无参构造方法里打印一句话
package com.yjc.beanlife; public class Student { private Integer age; private String name; public Student() { System.out.println("初始化时执行无参构造!"); } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
在applicationContext.xml把Student声明到Spring 容器当中,设置bean节点的值为singleton(当然也可以不设置,因为默认值就是singleton)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="student" class="com.yjc.beanlife.Student" scope="singleton"/> </beans>
执行测试方法,在测试方法里加载配置文件,创建Spring容器
package com.yjc.beanlife; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class BeanTest { public static void main(String[] args) { ApplicationContext applicationContext=new ClassPathXmlApplicationContext("com/yjc/beanlife/applicationContext.xml"); } }
测试结果
由上图可见,当bean节点的scope属性的值为singleton时,无论你是否使用这个Bean对象,bean初始化的时机是和Spring容器同时创建的。就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象。
接下来把bean节点的scope属性值更改为prototype,修改测试方法
package com.yjc.beanlife; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class BeanTest { public static void main(String[] args) { ApplicationContext applicationContext=new ClassPathXmlApplicationContext("com/yjc/beanlife/applicationContext.xml"); Student student = applicationContext.getBean("student", Student.class); Student student1 = applicationContext.getBean("student", Student.class); System.out.println(student); System.out.println(student1); } }
测试结果如下
当bean节点的scope属性值为prototype时,bean的初始化时机就变为了,当你去获取Bean对象的时候,Spring容器才会创建一个对象,而且每一次创建的都是不同的对象。
根据经验,对有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。