Spring Bean的作用域
目前Bean的作用域有以下6种,
作用域 | 描述 |
---|---|
singleton | 在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,bean作用域范围的默认值。 |
prototype | 每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean()。 |
request | 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于web的Spring WebApplicationContext环境。 |
session | 同一个HTTP Session共享一个Bean,不同Session使用不同的Bean。该作用域仅适用于web的Spring WebApplicationContext环境。 |
application | 限定一个Bean的作用域为ServletContext的生命周期。该作用域仅适用于web的Spring WebApplicationContext环境。 |
global-session | 全局session,集群下的session,如果不是集群环境,和session没去别。 |
1.作用域为Singleton的Bean,默认也是Singleton
作用域为Singleton的Bean只会在IOC容器中创建一个共享的bean实例,每次从IOC容器中拿到的Bean都是同一个。
下面举一个例子来说明
1、首先创建一个Bean
public class Student {
private String study;
public String getStudy() {
return study;
}
public void setStudy(String study) {
this.study = study;
}
}
2、在Spring文件配置上面这个Bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
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 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="student" class="com.springtest2.scope.Student" scope="singleton" />
</beans>
3、编写测试类
@Test
public void testSingleton(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext5.xml");
Student student = (Student) context.getBean("student");
student.setStudy("我在学英语。。。");
System.out.println(student.getStudy());
Student student2 = (Student) context.getBean("student");
System.out.println(student2.getStudy());
System.out.println(student == student2);
}
4、打印结果
我在学英语。。。
我在学英语。。。
true
2.作用域为prototype的Bean
当bean作用域scope为prototype的时候,每次从IOC容器中获取的Bean都是一个新创建的。prototype是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象
这个测试,我们只需要把scope改为prototype
<bean id="student" class="com.springtest2.scope.Student" scope="prototype" />
再次打印结果
我在学英语。。。
null
false
3.使用注解定义 bean 的作用域
- 修改Student类。
- 修改xml文件,进行包扫描。
- 测试类不用变,直接执行,和之前运行结果医院一样。
@Component("student")
@Scope("prototype")
public class Student {
private String study;
public String getStudy() {
return study;
}
public void setStudy(String study) {
this.study = study;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<!--<bean id="student" class="com.springtest2.scope.Student" scope="singleton" />-->
<!--<bean id="student" class="com.springtest2.scope.Student" scope="prototype" />-->
<context:component-scan base-package="com.springtest2.scope" />
</beans>
注意
request,session和application
这三个作用域都是基于web的Spring WebApplicationContext实现的,只有在web环境下(比如XmlWebApplicationContext)中才能使用。
如果开发者仅仅在常规的Spring IoC容器中比如ClassPathXmlApplicationContext在中使用这些作用域,那么将会抛出一个IllegalStateException来说明使用了未知的作用域。
4、请求作用域
<bean id="loginAction" class="com.foo.LoginAction" scope="request"/>
Spring容器会在每次用到loginAction来处理每个HTTP请求的时候都会创建一个新的LoginAction实例。也就是说,loginActionBean的作用域是HTTP Request级别的。 类似多例。
5、会话作用域
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
每次创建UserPreferences也是一个全新的,类似多例。
6、全局作用域
<bean id="appPreferences" class="com.foo.AppPreferences" scope="application"/>
Spring容器会在整个web应用范围使用到appPreferences的时候创建一个新的AppPreferences的实例。也就是说,appPreferencesBean是在ServletContext级别的,作为常规的ServletContext属性类似单例,但是也有如下不同之处:
-
application作用域是每个ServletContext中包含一个,而不是每个SpringApplicationContext之中包含一个(某些应用中可能包含不止一个ApplicationContext)。
-
application作用域仅仅作为ServletContext的属性可见,单例Bean是ApplicationContext可见。