Spring中Bean的五个做用域

当经过spring容器建立一个Bean实例时,不只能够完成Bean实例的实例化,还能够为Bean指定特定的做用域。Spring支持以下5种做用域:web

  • singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例面试

  • prototype:原型模式,每次经过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例spring

  • request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不一样的Bean实例。只有在Web应用中使用Spring时,该做用域才有效安全

  • session:对于每次HTTP Session,使用session定义的Bean豆浆产生一个新实例。一样只有在Web应用中使用Spring时,该做用域才有效session

  • globalsession:每一个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型状况下,仅在使用portlet context的时候有效。一样只有在Web应用中使用Spring时,该做用域才有效mvc

  其中比较经常使用的是singleton和prototype两种做用域。对于singleton做用域的Bean,每次请求该Bean都将得到相同的实例。容器负责跟踪Bean实例的状态,负责维护Bean实例的生命周期行为;若是一个Bean被设置成prototype做用域,程序每次请求该id的Bean,Spring都会新建一个Bean实例,而后返回给程序。在这种状况下,Spring容器仅仅使用new 关键字建立Bean实例,一旦建立成功,容器不在跟踪实例,也不会维护Bean实例的状态。app

  若是不指定Bean的做用域,Spring默认使用singleton做用域。Java在建立Java实例时,须要进行内存申请;销毁实例时,须要完成垃圾回收,这些工做都会致使系统开销的增长。所以,prototype做用域Bean的建立、销毁代价比较大。而singleton做用域的Bean实例一旦建立成功,能够重复使用。所以,除非必要,不然尽可能避免将Bean被设置成prototype做用域。性能

 

曾经面试的时候有面试官问我spring的controller是单例仍是多例,结果我傻逼的回答固然是多例,要否则controller类中的非静态变量如何保证是线程安全的,这样想起彷佛是对的,可是不知道(主要是我没看过spring的源码,不知道真正的内在乎图)为何spring的controller是单例的。先看看spring的bean做用域有几种,分别有啥不一样。spring bean做用域有如下5个:singleton:单例模式,当spring建立applicationContext容器的时候,spring会欲初始化全部的该做用域实例,加上lazy-init就能够避免预处理;prototype:原型模式,每次经过getBean获取该bean就会新产生一个实例,建立后spring将再也不对其管理;====下面是在web项目下才用到的===request:搞web的你们都应该明白request的域了吧,就是每次请求都新产生一个实例,和prototype不一样就是建立后,接下来的管理,spring依然在监听session:每次会话,同上global session:全局的web域,相似于servlet中的application好了,上面都说了spring的controller默认是单例,那很天然就是singleton了。再看一个例子,看看单例会不会有我说的那种问题(就是类中定义的非静态变量线程安全问题),固然下面这个例子我是实验过的, 要否则也不敢发出来为何spring要默认是单例呢?缘由有二:一、为了性能。二、不须要多例。一、这个不用废话了,单例不用每次都new,固然快了。二、不须要实例会让不少人迷惑,由于spring mvc官方也没明确说不能够多例。  我这里说不须要的缘由是看开发者怎么用了,若是你给controller中定义不少的属性,那么单例确定会出现竞争访问了。  所以,只要controller中不定义属性,那么单例彻底是安全的。下面给个例子说明下: 默认单例的1|2package com.lavasoft.demo.web.controller.lsh.ch5;import org.springframework.context.annotation.Scope;import org.springframework.stereotype.Controller;import org.springframework.ui.ModelMap;import org.springframework.web.bind.annotation.RequestMapping;/** * Created by Administrator on 14-4-9. * * @author leizhimin 14-4-9 上午10:55 */@Controller@RequestMapping("/demo/lsh/ch5")public class MultViewController {privateintindex =0;         //非静态    @RequestMapping("/show")    publicStringtoShow(ModelMap model) {        System.out.println(++i);        return"/lsh/ch5/show";    }    @RequestMapping("/test")    publicStringtest() {        System.out.println(++i);        return"/lsh/ch5/test";    }}改成多例的(就是在class上面加一个@Scope("request")):1 | 1今后可见,单例是不安全的,会致使属性重复使用。最佳实践:一、不要在controller中定义成员变量。二、万一必需要定义一个非静态成员变量时候,则经过注解@Scope("prototype"),将其设置为多例模式。
相关文章
相关标签/搜索