关于spring的singleton bean

Spring IoC容器中只会存在一个共享的bean实例,这个单一实例会被存储到单例缓存(singleton cache)中,并且所有针对该bean的后续请求和引用都将返回被缓存的对象实例。我想知道设计模式中的Singleton模式与spring中的singleton bean之间有什么区别?
还有个比较傻的问题:用户登录后获得一个session,很多用户对bean进行操作,而bean是单例的,那bean对象中的数据岂不是乱了? :oops:

[b]问题补充:[/b]
一楼的朋友好像没有仔细看问题,答非所问啊。
我查资料说,“singleton bean的作用域可以描述为一个container对应一个bean实例”
在问答里也有朋友提出了跟我相似的疑问[url]http://www.iteye.com/problems/27340[/url]
[b]问题补充:[/b]
补充一楼:spring相对于EJB来说“对所有有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。”

那就是说,在classloader中只有一个singleton bean,说的在准确点就是“singleton bean在初始化后只有一个单例存在于spring container中”?

但是资料上说“Spring的singleton bean概念与“四人帮”(GoF)模式一书中定义的Singleton模式是[b]完全不同[/b]的。经典的GoF Singleton模式中所谓的对象范围是指在每一个ClassLoader中指定class创建的实例有且仅有一个。把Spring的singleton作用域描述成一个container对应一个bean实例最为贴切。亦即,假如在单个Spring容器内定义了某个指定class的bean,那么Spring容器将会创建一个且仅有一个由该bean定义指定的类实例。”

它的意思好像是说,在一个ClassLoader中可能有多个container,而一个container中只能有一个singleton bean,我理解的对吗?哪位能再解释下?

[b]问题补充:[/b]
感谢大家的回答,但是分只能给一个人,我觉得heaven的回答我很满意。

5个回答

Spring中的singleton的bean与单例对象起到的做用是一持的,
Spring的singleton参照的是同一IOC容器的单实例,对象在容器中得到缓存;
单例模式的单实例对象是参照同一Java虚拟机实例,
它们都是表明在一定范围内只有一个对象实例,只是实现方式不同,但Spring中的singleton对象用了单例模式的好处,而去掉了单例模式的坏处.比如单例模式的类是不可继承的,但Spring的JavaBean不受此限制,等等...
单实例一般都是无状态的,业务一般都是无状态的,所以可以配置成singleton,并且这有助于对象的重用和节省内存空间的分配.
当然多个用户操作同一对象,会出现并发问题,解决办法要么是配置成prototype形式的,牺牲空间,要么进行同步,牺牲时间,换取正确性.

一个虚拟机实例中可以有多个ClassLoader,但一个类型在同一个虚拟机实例中只会被加载一次,只会被一个ClassLoader加载一次,一个容器占有一个虚拟机实例,那么容器中的唯一实例相对虚拟机实例是唯一的这也是成立的.
但单例模式如果在同一虚拟机实例范围出现第二个实例,这会认为所写的单例类是有缺陷的,但Spring中你配置在容器中的Bean同容器保证它是单实例的,但容器外的你可以再生成此类的第二个,第三个,第N个对象,这是完全可以的, 并且Spring的容易测试性的模拟对象往往都是容器外的对象.

Bean以两种形态存在:singletons形式和prototypes形式.如果在中指定Bean的作用范围为scope="prototype",将Bean返回给调用者,调用者负责Bean后续生命的管理,spring不再管理这些Bean的生命周期.如果作用范围设置为scope="singleton",则将Bean放入Spring IOC容器的缓存池中,并将Bean引用返回给调用者,spring继续对这些Bean进行后续的生命管理. 默认属性是singleton.

在默认情况下,spring的ApplicationContext容器在启动时,自动实例化所有singleton的Bean并缓存于容器中.虽然启动时会花费一些时间,但带来两个好处:首先对Bean提前的实例化操作会及早发现一些潜在的配置问题.其次Bean以缓存的方式保存,当运行时使用到该Bean时就无须再实例化了,加快了运行效率.如果用户不希望在容器启动时提前实例化singleton的Bean,可以通过lazy-init属性进行控制,lazy-init="true"的Bean在某些情况下依旧会提前实例化:如果该Bean被其它需要提前实例化的Bean引用到,spring也将忽略延迟实例化的设置.

当Bean以prototype形态存在时,每次对这个Bean的实例请求都会导致一个新的实例的创建.当用户需要不受其他用户对象影响的对象或有类似的需求时,这是一个较理想的解决办法.
Bean 默认是以singleton形态存在的,除非你另外显式加以指定.留神,当把Bean的设置改为prototype模式时,每次对这个bean的实例请求都会导致一个新的Bean实例被创建,而这可能并不是你所期望的.所以,只应该在确实需要的情况下把Bean设置为prototype模式.

spring中的单例是指容器中只有一个实例,当然是指spring自身实现的ioc容器,也是基于classloader唯一的

是设计模式中的Singleton模式的一种实现而已

当然,如果bean中有成员变量的话,那多个用户操作bean的话,是会把bean对象中的数据搞乱了

在一个ClassLoader中可能有多个container,而一个container中只能有一个singleton bean。
这样说应该是合理的,因为在同一个JVM应用中可以开启多个Spring应用,如果用的是同一个ClassLoader,自然就代表可以有多个container;而既然是单例的,每个Container肯定要根据Bean的ID去维护它在这个容器中的唯一性,所以只能有一个单例的bean。

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问