论坛首页 Java企业应用论坛

Spring Singleton的陷阱

浏览 27030 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2006-12-25  
Feiing 写道
Ivan Li 写道
ACEGI我清楚,我在上面发的帖子你没看我已经写了为什么出错吗?
1:我是为了在Service层能够得到用户信息
2:不想从参数里传入用户信息
3:为了给继承类提供方便,所以我在BaseService里提供了方法
 protected UserContext getUserContext()  
 {  
     Authentication auth = SecurityContextHolder.getContext().getAuthentication();  
     return (UserContext) auth.getPrincipal();  
 }  

在基类中如果每次调用super.getUserContext()是肯定没问题的,因为这就是在调用ACEGI中ContextHolder中的方法,但是在继承类中保存了一个本地变量,当然会错了。这怎么是误导?
只不过对于某些程序员来说他并不知道Spring怎么处理,所以在继承类中写了一个本地变量来保存用户信息,而且在单元测试中也不会发现问题。



呵呵, 我倒是觉得你所谓的 "某些程序员" 是被你误导才会这样做, 明明是对 Context 的获取, 竟然不是 static 的, 还做成 BaseService 的 protected 方法, 奇怪的用法

满足上面的三个条件,你有什么高招?你无法要求组内所有的人都很清楚Spring
0 请登录后投票
   发表时间:2006-12-25  
gongzyx 写道
这个就是个java基本概念不清楚的结果,其实和spring根本没什么关系。singleton在jvm里面只会有一个实例,lz的情况,属性变量在唯一实例产生的时候被赋值,以后当然不会改变了。
对于singleton的对象,还是stateless比较好点。

这个我在一楼就分析出来了
0 请登录后投票
   发表时间:2006-12-25  
不清楚自然会用得不好

就像俺们组里的成员用exception一样,到处乱用,乱catch

后来的办法就是专门开个会,统一讨论一下,再定制标准
0 请登录后投票
   发表时间:2006-12-25  
Ivan Li 写道

满足上面的三个条件,你有什么高招?你无法要求组内所有的人都很清楚Spring


不知道 java 里面有一种叫 Util 的方法?
0 请登录后投票
   发表时间:2006-12-25  
Feiing 写道
Ivan Li 写道

满足上面的三个条件,你有什么高招?你无法要求组内所有的人都很清楚Spring


不知道 java 里面有一种叫 Util 的方法?

写成Util方法,跟放在Base里有什么两样?如果提供了Util方法,写继承类的老哥一样回怎么写
 public class SomeServece extends BaseService implements SomeInterFace    
 {  
     private UserInfo user = someUtil.getUserInfo();  
       
     public someMethod()  
     {  
        int userID = this.user.getUserID();  
        String userName = this.user.getUserName();  
        //bla bla do something user userID and userNaem  
 }  
 }      

问题不是还是存在?
0 请登录后投票
   发表时间:2006-12-25  
这种老哥, 还是去做别的行业吧
0 请登录后投票
   发表时间:2006-12-25  
这篇帖子的主要目的也是在说明四楼的哥们说的事情
flyspider 写道
Spring建议以singleton方式注入的依赖尽量是stateless的

只不过这个在项目中真实的出现了,所以发贴记下来
0 请登录后投票
   发表时间:2006-12-25  
Feiing 写道
这种老哥, 还是去做别的行业吧

人都需要一个成长的过程的,不能把人一棒子打死,不能期待项目组里的都是老鸟,怎么都会有些小鸟的,小鸟只要勤奋认学,总会成为老鸟的!
0 请登录后投票
   发表时间:2006-12-25  
ahuaxuan 写道
象楼主这样写肯定出错呀,大家都用一个service对象,你又把user设置为它的全局变量,而且还这样写:private UserInfo user = super.getUserInfo();   ,大错特错,第一,spring管理的单列模式的bean中的全局变量应该是无状态的(这一点无论哪个文档上都有写吧,看来楼主对spring不是很熟,user明显是有状态的怎么能用作全局变量呢,肯定要把super.getUserInfo()放在service具体的方法里),第二看到楼上很多人不知道在说什么,不知所芸,有人说“可以修改配置文件,修改参数吧!!”,还有人说“改改配置,写个全局变量,什么问题也就解决了,哪有这么麻烦”,还有人说用ThreadLocal,acegi这种得到用户的方式本来就是ThreadLocal,还需要再用一个ThreadLocal吗??其实关键不在ThreadLocal这个地方。上面有个兄弟说得其实很清楚明白,只是我看大家都没有理解,flyspider说道:
引用
Spring建议以singleton方式注入的依赖尽量是stateless的

这才是正确的,只不过大家都没有明天他在说什么

这位仁兄貌似没有明白我在说什么?
0 请登录后投票
   发表时间:2006-12-25  
feiing正确,楼主没有明白我的话,呵呵,可能我说得不够明白,全局变量会在实例初始化的时候赋值,private UserInfo user = super.getUserInfo(); 这样写,这个user变量只会被一次赋值(产生这个service对象的时候),不会再变了,并且,user是代表状态的,不能够作为service(singleton)的全局变量的,这在哪里都有说明的呀,所以不是我不明白你在说什么,是你不明白我在说什么,我说
引用
你又把user设置为它的全局变量,而且还这样写:private UserInfo user = super.getUserInfo(); ,大错特错,
,这还不够清楚吗。 一是只会被赋值一次,二是如果多线程修改user会造成数据紊乱(虽然你这里没有修改,但是你这样用会误导组里其他不知道得成员,使他们认为这样用是没有问题得),单例的service里不能放有状态的,这是原则,难道我说得真得不够明白吗???
我明白你的意思,你就是找出了个原因,真正的有一个原则性的东西你违反了,现在应该明白点了吧
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics