Spring中Bean的作用域详解
- Bean简介
- Bean作用域
- Singleton介绍
- Prototype介绍
- Request介绍
- Session介绍
Bean简介
在Spring中,组成应用程序的主体、由SpringIoC容器所管理的对象,被称之为bean。简单来讲,也就是由IoC容器进行初始化、装配、管理(生命周期和依赖关系)的对象。
Bean作用域
其中request、session的作用域仅在基于web的SpringContext环境中使用。
Singleton介绍
Spring缺省作用域,Singleton是单例类型,默认在创建容器时就自动创建了一个bean的对象,这样不管是否使用,都已经存在,并且每次获取到的是同一对象。
当一个bean的作用域为Singleton,那么SpringIoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。
XML中将一个bean定义为Singleton:
<bean id="user" class="com.ahy.pojo.User" scope="singleton">
</bean>
测试:
@Test
void test01() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicaitonContext.xml");
User user1 =(User) context.getBean("user");
User user2 =(User) context.getBean("user");
System.out.println(user1 == user2);//true
}
配置类中声明bean为Singleton:
@Configuration
public class SpringConfiguration {
@Bean
@Scope("singleton")
public People people(){
return new People("jack",55);
}
public class People{
private String name;
private int age;
public People(String name, int age) {
this.name = name;
this.age = age;
}
}
}
测试:
@Test
public void test01(){
AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext(SpringConfiguration.class);
User.People people1 =(User.People) context.getBean("people");
User.People people2 =(User.People) context.getBean("people");
System.out.println(people1 == people2 );//true
}
设置bean为懒加载,也就是在调用容器的getBean()方法时再加载:
<bean id="people" class="com.ahy.pojo.User.People"
lazy-init="true"></bean>
Prototype介绍
Prototype是原型类型,在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,并且我们每次获取到的对象都不是同一个对象。
当一个bean的作用域为Prototype,表示一个bean定义对应多个对象实例。Prototype作用域的bean会导致在每次对该bean请求时(将其注入到另一个bean中,或者调用容器的getBean()方法),都会创建一个新的bean实例。
根据经验,对有状态的bean应该使用Prototype作用域,而对无状态的bean应该使用Singleton作用域。
XML中将bean定义为Prototype:
<bean id="people" class="com.ahy.pojo.User.People" scope="prototype"></bean>
或者:
<bean id="people" class="com.ahy.pojo.User.People" singleton="false"></bean>
测试:
@Test
public void test01(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
User user1 =(User) context.getBean("user");
User user2 =(User) context.getBean("user");
System.out.println(user1 == user2);//false
}
配置类中声明bean为Prototype:
@Configuration
public class SpringConfiguration {
@Bean
@Scope("prototype")
public People people(){
return new People("jack",55);
}
public class People{
private String name;
private int age;
public People(String name, int age) {
this.name = name;
this.age = age;
}
}
}
测试:
@Test
public void test01(){
// ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext(User.class);
User.People user1 =(User.People) context.getBean("people");
User.People user2 =(User.People) context.getBean("people");
System.out.println(user1 == user2);//false
}
Request介绍
当一个bean作用域为Request,表示在一次HTTP请求中,一个bean对应一个实例;即每个HTTP请求都会有各自的bean实例。该作用域仅在基于web的SpringApplicaitonContext情形下有效。
XML中将bean定义为Request:
<bean id="loginAction" class="com.ahy.LoginAction" scope="request"></bean>
针对每次HTTP请求。Spring容器会根据loginAction bean的定义创建一个全新的LoginAction bean实例,且该实例仅在当前HTTP request请求内有效,因此可以根据需要放心的更改该实例的内部状态,而其他请求中根据loginAction bean定义创建的实例,将不会看到这些特定于某个请求的状态变化。当处理请求结束,request作用域的bean实例将被销毁。
Session介绍
当一个bean的作用域为Session,表示在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
XML中将bean定义为Session:
<bean id="userPreferences" class="com.ahy.UserPreferences" scope="session"/>
针对某个HTTP Session,Spring容器会根据userPreferences bean定义创建一个全新的userPreferences bean实例,且该userPreferences bean仅在当前HTTP Session内有效。与request作用域一样,可以根据需要放心的更改所创建实例的内部状态,而别的HTTP Session中根据userPreferences创建的实例,将不会看到这些特定于某个HTTP Session的状态变化。当HTTP Session最终被废弃的时候,在该HTTP Session作用域内的bean也会被废弃掉。