**Bean的作用域**:
作用域:一般指的是对象或者变量之间的可见范围。而在Spring容器中是指其创建的Bean对象相对于其他Bean对象的请求可见范围。
Spring提供Singleton和prototype两种基本作用域,另外提供Request、session、global、session三种web作用域;Spring还允许用户制定自己的作用域。
基本的作用域
**一:Singleton:**指Singleton作用域的Bean只会在每个S平IOC容器中存在一个实例,而且其完整生命周期完全由Spring容器管理。对于所有获取Bean的操作Spring容器将只返回同一个Bean。
GoF单例设计模式指“保证一个类仅有一个实例,并提供一个访问它的全局访问点”,介绍了两种实现:通过在类上定义静态属性保持该实例和通过注册表方式。
**1)通过在类上定义静态属性保持该实例**:一般指一个Java虚拟机 ClassLoader装载的类只有一个实例,一般通过类静态属性保持该实例,这样就造成需要单例的类都需要按照单例设计模式进行编码;Spring没采用这种方式,因为该方式属于侵入式设计;
package org.liang.test;
/**
* 单例类
*/
public class Singleton {
private String name;
private Singleton(){};
public static Singleton getInstance(){
return new Singleton();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class TsetSingleton{
public static void main(String [] args){
Singleton singleton = Singleton.getInstance();
singleton.setName("关羽");
System.out.println(singleton.getName());
}
}
**2) 通过注册表方式:** 首先将需要单例的实例通过唯一键注册到注册表,然后通过键来获取单例,让我们直接看实现吧,注意本注册表实现了Spring接口“SingletonBeanRegistry”,该接口定义了操作共享的单例对象,Spring容器实现将实现此接口;所以共享单例对象通过“registerSingleton”方法注册,通过“getSingleton”方法获取,消除了编程方式单例,注意在实现中不考虑并发。
package org.liang.test;
import org.liang.entity.Persion;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Created by rcc on 2018/2/2.
*/
public class TestScope {
public static void main(String [] args){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
Persion persion = context.getBean(Persion.class);
Persion persion1 = context.getBean(Persion.class);
System.out.println(persion == persion1);
System.out.println("=======================================================");
Persion persion2 = new Persion();
Persion persion3 = new Persion();
System.out.println(persion2 == persion3);
System.out.println("=======================================================");
System.out.println(persion);
System.out.println(persion1);
/**
* 返回结果:
* true
*======================================================
* false
*
* 这就很奇怪了是不是,使用容器获得的两个所谓的新的对象居然是同一个对象,这和我们直接new两个对象的结果刚好相反。
* 不过仔细想一想也不奇怪,既然对象是从Spring容器中获取的,会不会是容器在对象创建的时候对对象进行了缓存呢?
*
* 基于这个猜想,我们将对象中的属性打印出来:
*
* Persion{name='doudou', nickName='zhuzhu', age=18}
* Persion{name='doudou', nickName='zhuzhu', age=18}
* 结果居然一模一样,返回的是同一个对象。
*
* 那么这到底是什么原因呢?
* <bean id="persion" class="org.liang.entity.Persion" scope="singleton">
<constructor-arg index="0" value="doudou"/>
<constructor-arg name="nickName" value="zhuzhu"/>
<constructor-arg type="java.lang.Integer" value="18"/>
</bean>
* 原因就是这个配置:scope="singleton" ,表示该对象是单例的,所以容器会缓存对象,每次获取的对象都是同一个。
* 在Spring容器中如果没指定作用域默认就是“singleton”。
*/
}
}
**二、prototype:即原型,**指每次向Spring容器请求获取Bean都返回一个全新的Bean,相对于“singleton”来说就是不缓存Bean,每次都是一个根据Bean定义创建的全新Bean。
<bean id="user" class="org.liang.entity.User" scope="prototype">
<property name="name" value="张三"/>
<property name="gender" value="男"/>
<property name="age" value="18"/>
</bean>
========================================================================================
User user = (User) context.getBean("user");
User user1 = (User) context.getBean("user");
System.out.println(user == user1);
/**
返回结果:
* =======================================================
false :每次获取的都是全新的对象
*/
**Web应用中的作用域:**
在Web应用中,我们可能需要将数据存储到request、session、global session。因此Spring提供了三种Web作用域:request、session、globalSession。
一、request作用域:表示每个请求需要容器创建一个全新Bean。比如提交表单的数据必须是对每次请求新建一个Bean来保持这些表单数据,请求结束释放这些数据。
二、session作用域:表示每个会话需要容器创建一个全新Bean。比如对于每个用户一般会有一个会话,该用户的用户信息需要存储到会话中,此时可以将该Bean配置为web作用域。
三、globalSession:类似于session作用域,只是其用于portlet环境的web应用。如果在非portlet环境将视为session作用域。
配置方式和基本的作用域相同,只是必须要有web环境支持,并配置相应的容器监听器或拦截器从而能应用这些作用域,我们会在集成web时讲解具体使用,大家只需要知道有这些作用域就可以了。
Spring学习--Bean的作用域
最新推荐文章于 2023-08-22 14:25:43 发布