Spring Bean 的5种作用域
Spring Bean 中所说的作用域,在配置文件中即是“scope” 在面向对象程序设计中作用域一般指对象或变量之间的可见范围。 而在Spring容器中是指其创建的Bean对象相对于其他Bean对象的请求可见范围。
在Spring 容器当中,一共提供了5种作用域类型,在配置文件中,通过属性scope来设置bean的作用域范围。 1.singleton: [html]view plain
copy
解析来我们详细的介绍每种作用域的功能: 1)singleton作用域 是指在Spring IoC容器中仅存在一个Bean的示例,Bean以单实例的方式存在,单实例模式是重要的设计模式之一,在Spring中对此实现了超越,可以对那些非线程安全的对象采用单实例模式。 接下来看一个示例: [html]view plain copy
- 1.
- 2.
- 3.
- 4.
文章图片
不仅在容器中通过对象引入配置注入引用相同的car bean,通过容器的getBean()方法返回的实例也指向同一个bean。 在默认的情况下Spring的ApplicationContext容器在启动的时候,自动实例化所有的singleton的bean并缓存于容器当中。
虽然启动时会花费一定的时间,但是他却带来了两个好处:
- 对bean提前的实例化操作,会及早发现一些潜在的配置的问题。
- Bean以缓存的方式运行,当运行到需要使用该bean的时候,就不需要再去实例化了。加快了运行效率。
2)prototype作用域 是指每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行new Bean()的操作。在默认情况下,Spring容器在启动时不实例化prototype的Bean。 接下来看一个示例: [html]view plain copy
- 1.
- 2.
- 3.
- 4.
文章图片
在默认情况下,Spring容器在启动时不实例化prototype这种bean。此外,Spring容器将prototype的实例交给调用者之后便不在管理他的生命周期了。
3)当用户使用Spring的WebApplicationContext时,还可以使用另外3种Bean的作用域,即request,session和globalSession。
在使用Web应用环境相关的Bean作用域时,必须在Web容器中进行一些额外的配置:
对于低版本Web容器配置: 用户可以使用http过滤器来进行配置并在url-pattern中对所有的页面进行过滤。 [html]view plain copy
requestContextFilter org.springframework.web.filter.RequestContextFilter requestContextFilter /*
- org.springframework.web.context.request.RequestContextListener
Spring容器的启动和关闭事件由web容器的启动和关闭事件来触发。 但如果Spring容器中的bean需要request、session和globalSession作用域的支持,Spring容器本身就必须获得web容器的http请求事件。以http请求事件来驱动bean的作用域的控制逻辑,也就是说通过配置RequestContextListener接口,Spring和web容器的结合就更紧密了。
那么接下来简单的介绍下这三种作用域。 1.request作用域 对应一个http请求和生命周期,当http请求调用作用域为request的bean的时候,Spring便会创建一个新的bean,在请求处理完成之后便及时销毁这个bean。 2.session作用域 Session中所有http请求共享同一个请求的bean实例。Session结束后就销毁bean。 3.globalSession作用域 与session大体相同,但仅在portlet应用中使用。 Portlet规范定义了全局session的概念。请求的bean被组成所有portlet的自portlet所共享。 如果不是在portlet这种应用下,globalSession则等价于session作用域。
接下来使用一个实例来演示下bean作用域的概念: 首先我们创建scope包,然后在包中创建两个Java Bean:老板(Boss.java)以及轿车(Car.java) [java]view plain copy
- public class Boss {
- private String name;
- private Car car;
- public Boss() {
- }
- public Car getCar() {
- return car;
- }
- public void setCar(Car car) {
- this.car = car;
- }
- @Override
- public String toString() {
- return "Boss{" +
- "name='" + name + '\'' +
- ", car=" + car +
- '}';
- }
- }
- public class Car {
- private String color;
- private String brand;
- private double price;
- public String getColor() {
- return color;
- }
- public void setColor(String color) {
- this.color = color;
- }
- public String getBrand() {
- return brand;
- }
- public void setBrand(String brand) {
- this.brand = brand;
- }
- public double getPrice() {
- return price;
- }
- public void setPrice(double price) {
- this.price = price;
- }
- }
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
[java]view plain copy
- public class Main {
- public static void main(String[] args){
- //加载配置文件,启动IoC容器
- BeanFactory factory=
- new FileSystemXmlApplicationContext("src/conf/conf-scope.xml");
- //获得bean实例
- Boss boss1=factory.getBean("boss1",Boss.class);
- Boss boss2=factory.getBean("boss2",Boss.class);
- Boss boss3=factory.getBean("boss3",Boss.class);
- System.out.println(boss1.getCar());
- System.out.println(boss2.getCar());
- System.out.println(boss3.getCar());
- }
- }
接下来再来简单的学习下在Spring当中如何自定义作用域: 在Spring 2.0中,Spring的Bean作用域机制是可以扩展的,这意味着,你不仅可以使用Spring提供的预定义Bean作用域,还可以定义自己的作用域,甚至重新定义现有的作用域(不提倡这么做,而且你不能覆盖内置的singleton和prototype作用域)
1.首先需要实现自定义Scope类: org.springframework.beans.factory.config.Scope 首先我们得实现config.scope这个接口,要将自定义scope集成到Spring容器当中就必须要实现这个接口。接口中只有两个方法,分别用于底层存储机制获取和删除这个对象。
2.在实现一个或多个自定义Scope并测试通过之后,接下来便是如何让Spring容器来识别新的作用域。我们需要注册自定义Scope类,使用registerScope方法 ConfigurableBeanFactory.registerScope(String scopeName, Scope scope) 其中:第一个参数是与作用域相关的全局唯一的名称,第二个参数是准备实现的作用域的实例。
3.在实现和注册自定义的scope类之后我们便来使用自定义的Scope: [html]view plain copy
- Scope customScope = new ThreadScope();
- beanFactory.registerScope(“thread”, customeScope);
推荐阅读
- 热闹中的孤独
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- 一个人的旅行,三亚
- 布丽吉特,人生绝对的赢家
- 慢慢的美丽
- 尽力
- 一个小故事,我的思考。
- 家乡的那条小河
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量