疯狂
STANDING ON THE SHOULDERS OF GIANTS
posts - 481, comments - 486, trackbacks - 0, articles - 1
BlogJava
::
首页
::
新随笔
::
联系
::
聚合
::
管理
注意spring, singleton不single! ?
Posted on 2010-08-30 00:41
疯狂
阅读(6900)
评论(12)
编辑
收藏
所属分类:
java
、
spring
、
web
spring的singleton真的会在整个应用中创建单一的对象吗?非也,他只会在内部springframework的一个applicationContext上下文中保持单利,但是如果有两个applicationContext呢?
首先看以下实例 :
首先定义一个bean 并注册为单利,非懒加载对象:
package
com.joe.service;
public
class
TestService
{
public
TestService()
{
System.out.println(
"
create TestService
"
);
}
}
配置:
<
bean id
=
"
testservice
"
class
=
"
com.joe.service.TestService
"
scope
=
"
singleton
"
lazy
-
init
=
"
false
"
></
bean
>
测试代码:
private
static
ApplicationContext context1;
private
static
ApplicationContext context2;
static
{
context1
=
new
ClassPathXmlApplicationContext(
new
String[]{
"
classpath:spring-bean_*.xml
"
});
context2
=
new
ClassPathXmlApplicationContext(
new
String[]{
"
classpath:spring-bean_*.xml
"
});
}
public
static
void
main(String[] args)
throws
SQLException, IOException {
System.out.println(
"
context1 中 testservice 是否单利?
"
+
context1.isSingleton(
"
testservice
"
));
TestService service
=
(TestService) context1.getBean(
"
testservice
"
);
System.out.println(service);
System.out.println(
"
context2 中 testservice 是否单利?
"
+
context2.isSingleton(
"
testservice
"
));
TestService service2
=
(TestService) context2.getBean(
"
testservice
"
);
System.out.println(service2);
System.out.println(service);
System.out.println(
"
context1 中 testservice 是否和context2 中 testservice 是一个对象?
"
+
(service
==
service2));
//
关键地方 两个ApplicationContext 中拿 到的是否是一个对象?
}
结果:
create TestService
create TestService
context1 中 testservice 是否单利?
true
com.joe.service.TestService@54c4ad
context2 中 testservice 是否单利?
true
com.joe.service.TestService@13c7378
com.joe.service.TestService@54c4ad
context1 中 testservice 是否和context2 中 testservice 是一个对象?
false
很明显在一个jvm应用中出现两个被标注为单利的实例。
spring内部通过上下文中的集合来管理对象,核心为beanFactory,而非通过asm等来动态改变类结构来控制类的scope。
我们跟着源码来看看:
在调用new ClassPathXmlApplicationContext实际上调用了
this(configLocations, true, null);其中的true代表要刷新上下文:而最终的refresh是这样的
if
(hasBeanFactory())
{
destroyBeans();
closeBeanFactory();
}
但是很费解的是hasBeanFactory的判断:
protected
final
boolean
hasBeanFactory()
{
synchronized
(
this
.beanFactoryMonitor)
{
return
(
this
.beanFactory
!=
null
);
}
}
其中的this.beanFactory是ClassPathXmlApplicationContext的实例的属性private DefaultListableBeanFactory beanFactory;
不用说this.beanFactory==null因为我们new了一个ClassPathXmlApplicationContext , beanFactory也没有初始化操作,也没有parentContext (因为我根本不知道有没有parentContext)而beanFactory也不是static的。
也就是说在第二次new ClassPathXmlApplicationContext的时候并不会refresh beanFactory 当然就会有两个单利的实例。
此问题在项目中出现,当时由于一个同事在自己的一个类里面的static区域new了ClassPathXmlApplicationContext用来测试忘记删掉, 而我们的所有类又是通过web容器来加载,结果就导致项目中出现单利对象出现两个的问题,结果害的那个苦啊!
希望大家在实际项目中注意到,也希望大家跟帖讨论下,我分析的是否正确,大家实际项目中有没有解决方案来避免这样的问题!
评论
#
re: 注意spring, singleton不single! ?
回复
更多评论
2010-08-30 10:01 by
隔叶黄莺
谢谢,又了解到一点知识,范围是基于 applicationContext,而不是 JVM。其实通常的单例,我们要更严格的来讲也不能说是基于 JVM,而是基于 ClassLoader 的。
#
re: 注意spring, singleton不single! ?
回复
更多评论
2010-08-30 10:38 by
forest
我测试了一下,发现两个test是相同的。
#
re: 注意spring, singleton不single! ?
回复
更多评论
2010-08-30 10:58 by
@joe
@forest
能提供下测试代码看看吗?
#
re: 注意spring, singleton不single! ?
回复
更多评论
2010-08-30 11:11 by
Lancelot
人家的singleton本来就是相对于容器的。
#
re: 注意spring, singleton不single! ?
回复
更多评论
2010-08-30 11:43 by
@joe
@Lancelot
但是真正的项目中要的是真正的单利,我感觉这种思想脱离了实际应用。给项目带来了麻烦这是事实。我不知道spring是处于何种思想?希望兄台给个解释!
#
re: 注意spring, singleton不single! ?
回复
更多评论
2010-08-30 11:57 by
@joe
查看spring的文档然后了解到实质,请看一下文档(来自spring官方文档)
3.4.1. The singleton scope
When a bean is a singleton, only one shared instance of the bean will be managed, and all requests for beans with an id or ids matching that bean definition will result in that one specific bean instance being returned by the Spring container.
To put it another way, when you define a bean definition and it is scoped as a singleton, then the Spring IoC container will create exactly one instance of the object defined by that bean definition. This single instance will be stored in a cache of such singleton beans, and all subsequent requests and references for that named bean will result in the cached object being returned.
请注意一下内容:
**********************************************
Please be aware that Spring's concept of a singleton bean is quite different from the Singleton pattern as defined in the seminal Gang of Four (GoF) patterns book. The GoF Singleton hard codes the scope of an object such that one and only one instance of a particular class will ever be created per ClassLoader. The scope of the Spring singleton is best described as per container and per bean.
*********************************************
This means that if you define one bean for a particular class in a single Spring container, then the Spring container will create one and only one instance of the class defined by that bean definition. The singleton scope is the default scope in Spring
当然spring是per container and per bean.
也就是(Scopes a single bean definition to a single object instance per Spring IoC container.
);
唉 以后注意。
#
re: 注意spring, singleton不single! ?
回复
更多评论
2010-08-30 12:02 by
@joe
@@joe
但为什么不使用GoF Singleton 呢??????
#
re: 注意spring, singleton不single! ?
回复
更多评论
2010-08-30 12:29 by
anders
@joe
但是真正的项目中要的是真正的单利,我感觉这种思想脱离了实际应用。给项目带来了麻烦这是事实。我不知道spring是出于何种思想?希望兄台给个解释!
...
有点无语。
第一joe没有弄清出spring提供单例范围。spring单例基于container的。
第二joe还没有弄清项目中单例的范围,“什么叫真正的项目真正的单例”,以偏盖全——以自己项目的需求覆盖全部的需求。
对于一个J2EE来说,如果运行在应用服务器下,一个应用服务器可以同时支持多个应用,单例的范围就应该是每个应用一个单例,就是spring的考虑,不能是
两个应用使用同一个单例,会出很多问题比如classload的问题。如果确实需要,则应自己扩展spring的scope,采用jndi的方式获取单例。
“什么叫真正的项目真正的单例”,单例是基于JVM的,还是基于OS的,还是基于内网的,还是基于整个互联网的。
基于JVM的给用静态变量;基于OS的给借助OS特性,比如文件系统;基于内网的和互联网的就根复杂了。。。。
#
re: 注意spring, singleton不single! ?
回复
更多评论
2010-08-30 13:22 by
@joe
@anders
首先感谢anders的恢复 !,让人更深入的了解了Singleton !
但是我的情况就是在一个应用中出现了这样的问题,既然一个应用中可以new 多个applicationContext,为什么不加以控制呢!我感觉不应该研发自己去注意这些东西,应该对于一个应用有一个Global Application足以,如果再new application的时候 直接指向前一个applicationContext!这样Singleton 在一个应用中应该可以得到解决!
#
re: 注意spring, singleton不single! ?
回复
更多评论
2010-08-31 11:16 by
xylz
@@joe
anders说的很明白了,spring是基于container的!这与单例的作用范围其实没有关系。。。
#
re: 注意spring, singleton不single! ?
回复
更多评论
2010-08-31 13:44 by
@joe
@xylz
spring是基于container的.我明白!
但是脱离实际项目谈这些是没有用,给项目带来风险的东西,都是值得考虑,值得注意的,概念谁都懂!
#
re: 注意spring, singleton不single! ?
回复
更多评论
2013-12-21 16:33 by
zb
争论有意义吗,说明白不就成了,孔已己似的.
新用户注册
刷新评论列表
只有注册用户
登录
后才能发表评论。
网站导航:
博客园
IT新闻
知识库
C++博客
博问
管理
相关文章:
JAVA Thread Dump 分析综述
关于java RMI在多网卡下(或者启动360,百度,腾讯等wifi共享下)无法连接问题(java.rmi.ConnectException: Connection refused to host: xx)
Quartz+Spring的集群配置(转)
java.awt.headless=true
dom4j通过xpath查询xml (转)
深入探讨 Java 类加载器
Java ClassLoader基础知识
synchronized 要注意的地方
关于java.lang.IllegalMonitorStateException
ThreadPoolExecutor运转机制详解 .
Powered by:
BlogJava
Copyright © 疯狂
日历
<
2010年8月
>
日
一
二
三
四
五
六
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
公告
公众号:
QQjava交流群:
51374316
留言簿
(11)
给我留言
查看公开留言
查看私人留言
随笔分类
all 生活杂谈(16)
android(18)
apache项目(20)
chart(1)
concurrent(5)
database(70)
dwr(3)
flex(6)
hibernate(25)
java (135)
javafx(2)
javascript
java安全(8)
java性能(19)
jbpm(1)
jquery(4)
linux(17)
lucene(1)
netty(3)
nginx(1)
others(2)
questions(31)
questions_hander(28)
spring(32)
struts(9)
swing
UML(2)
unix(13)
web(45)
webservice(9)
xml(5)
敏捷(6)
方法论(28)
架构(21)
测试(1)
缓存
网络通讯(9)
读代码(6)
项目管理(19)
相册
我的相册
搜索
积分与排名
积分 - 2834706
排名 - 2
最新随笔
1. 后续内容请移步公众号“duomi88”
2. Netty百万级推送服务(转)
3. Netty 概述(转)
4. Netty优雅退出机制和原理(转)
5. 使用JavaMail SearchTerm 收取邮件
6. JAVA Thread Dump 分析综述
7. oracle 索引字段包含date类型,使用spring jdbc更新时不走索引,而是走table access full的问题
8. FTP主动模式和被动模式的比较(转载)
9. 关于java RMI在多网卡下(或者启动360,百度,腾讯等wifi共享下)无法连接问题(java.rmi.ConnectException: Connection refused to host: xx)
10. (转)Oracle数据库如何授权收费(Database Licensing)
11. 成功的 Web 应用系统性能测试 (转载)
12. It is indirectly referenced from required .class file异常
13. (转)svn cleanup failed–previous operation has not finished; run cleanup if it was interrupted
14. automation服务器不能创建对象 解决办法
15. ERROR: transport error 202: gethostbyname: unknown host 解决办法
16. JavaScript 跨浏览器事件处理(转)
17. 函数声明 VS 函数表达式(转)
18. ORA-06548错误
19. 项目规划与管理记录2
20. tmpFile.renameTo(classFile) failed
21. redhat6.4 64位安装rlwrap
22. ora-01031:insufficient privileges
23. mysql远程连接问题 Access denied for user 'root'@' ip ' (using password: YES)
24. dbcp重连(转)
25. 解决Vmware Workstation上安装Linux系统不能SSH远程连接的问题
26. URL最大长度限制(转)
27. 用MyEclipse测试发送email时报java.lang.NoClassDefFoundError: com/sun/mail/util/LineInputStream
28. 我应该采用哪一种 WSDL 样式?(转载)
29. linux 挂载ntfs usb 出现mount: unknown filesystem type 'ntfs'
30. 11g oracle 用户密码过期问题
最新评论
1. re: Oracle物化视图创建全过程(转)
评论内容较长,点击标题查看
--ya
2. re: Oracle物化视图创建全过程(转)
评论内容较长,点击标题查看
--ya
3. re: 11g oracle 用户密码过期问题
问问
--是是是
4. re: mysql远程连接问题 Access denied for user 'root'@' ip ' (using password: YES)
asdfsadf
--asdf
5. re: struts(il8n)实现国际化的一个例子
在啥地方
--正常