Spring的Bean-singleton模式
来源:互联网 发布:北京美工设计培训 编辑:程序博客网 时间:2024/06/05 14:29
一.问题
在spring中,Bean的scope默认为singleton。可能我们会把spring的singleton与设计模式中的singleon
类比然后等价。事实是:在spring中的singleton不是以单例模式创建,而是在容器中以单例存在。
二.源码分析(这里以spring3.2.0为例)
创建一个示例,通过调试找到入口在:org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean中,这里只贴出主要部分。
如果实例已经存在,则直接取出使用:
//获取已经注册的实例 Object sharedInstance = getSingleton(beanName); //实例已经存在 if (sharedInstance != null && args == null) { if (logger.isDebugEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } } //如果缓存中已经存在,直接取出 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); }
如果实例还不存在,则进行创建:
//如果正在创建,异常返回 // Fail if we're already creating this bean instance: // We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); }
//scope==singleton的创建 if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { public Object getObject() throws BeansException { try { //createBean()反射创建实例 return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. //创建异常则销毁 destroySingleton(beanName); throw ex; } } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);} //scope==prototype的创建方式 else if (mbd.isPrototype()) { //创建新实例 // It's a prototype -> create a new instance. Object prototypeInstance = null; try { //创建前的回调:说明实例已经在创建 beforePrototypeCreation(beanName); //反射创建实例 prototypeInstance = createBean(beanName, mbd, args); } finally { //创建后的回调:标记实例不存在,因为是多例创建 afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } //后面还有其他scope的创建 ......
spring中的单例是只在容器中的存在方式,而不是创建方式。
三.singleton线程安全问题
spring框架中的单例Bean不是线程安全的。
spring框架将单例的Bean进行统一管理,但是允许多线程访问。所以对于无状态的Bean(没有实例变量的对象,比如:dao层的Bean),使用singleton是线程安全的;但是对于有状态的Bean(就是有实例变量的对象,比如:模型层的对象),使用singleton就是线程不安全的,解决方法可以是(a):时间换空间:线程同步机制;(b)空间换时间:改用prototype模式;或者使用ThreadLocal。
对于有状态的Bean使用prototype模式比较方便。
阅读全文
0 0
- Spring的Bean-singleton模式
- spring创建bean模式singleton与prototype的区别
- Spring学习笔记 关于Spring创建Bean的模式-Singleton(单例模式)和Prototype
- Spring学习笔记 关于Spring创建Bean的模式-Singleton(单例模式)和Prototype
- 关于Spring创建Bean的模式-Singleton(单例模式)和Prototype
- [spring]sping的singleton类型bean与单例模式的区别
- Spring中Bean的作用域singleton, prototype
- Spring 受管理 Bean scope 的 prototype 和 singleton 区别
- spring bean scope=prototype/singleton的差别
- 《转》详解Spring中bean的scope singleton prototype request...
- Spring源码学习之bean的prototype和singleton类型
- spring Bean的作用域(singleton&prototype)
- 解决Spring中singleton中注入prototype Bean的问题
- Spring中bean的模式
- Spring中Singleton模式的线程安全
- Spring中Singleton模式的线程安全
- Spring中Singleton模式的线程安全
- Spring中Singleton模式的线程安全
- 傻瓜式学习webpack(一)——建立项目
- ubuntu和centos系统的下文件的压缩解压命令
- Linux基础-0001-文件查找:locate与find
- 多任务学习“Fine-grained Recognition in the Wild: A Multi-Task Domain Adaptation Approach”
- java作业
- Spring的Bean-singleton模式
- nginx 设置开机自启 (加入开机加载服务)
- ubuntu14.04设置SSH免密码登陆
- 英语纠音(一)
- 11.2 T3.tree(树形dp+期望)
- 1.4.7 汉明码
- 阿里云MaxCompute加速全球化布局 11月1日北京、马来西亚两地开服
- C# 调整控件Z序
- 66.设计模式笔记-工厂方法模式