锁定老帖子 主题:Spring Singleton的陷阱
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2006-12-22
我还看好它的SecurityContextHolder,通过代码 Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 我可以很容易在系统任意一层得到用户的信息,而不用把用户信息在参数里传来传去,(这也是struts的缺点之一) 但是我在每一次要得到用户信息的时候都写上面的一段代码,未免有些麻烦,所以我在BaseService, BaseDao里都提供了如下方法: /** * get current login user info * @return UserInfo */ protected UserInfo getUserInfo() { return getUserContext().getUserInfo(); } /** * get current login user context * @return UserContext */ protected UserContext getUserContext() { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); return (UserContext) auth.getPrincipal(); } 这样在其他的Service和Dao类里可以通过 super.getUserContext(), super.getUserInfo() 来得到用户的信息,这也为问题的产生提供了温床。请看如下代码: public class SomeServece extends BaseService implements SomeInterFace { private UserInfo user = super.getUserInfo(); public someMethod() { int userID = this.user.getUserID(); String userName = this.user.getUserName(); //bla bla do something user userID and userNaem } } 这段代码在单元测试的时候不会用任何问题,但是在多用户测试的情况下,你会发现任何调用SomeService里someMethod()方法 的userID和userName都是同一个人,也就是第一个登陆的人的信息。Why? 其根本原因是Spring的Bean在默认情况下是Singleton的,Bean SomeServece的实例只会生成一份,也就是所SomeServece实例的user 对象只会被初始化一次,就是第一次登陆人的信息,以后不会变了。所以BaseService想为开发提供方便,却给开发带来了风险 正确的用法应该是这样的 public class SomeServece extends BaseService implements SomeInterFace { public someMethod() { int userID = super.getUserInfo().getUserID(); String userName = super.getUserInfo().getUserName(); //bla bla do something user userID and userNaem } } 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2006-12-22
刚刚看了一下,挑一点小刺:
1、默认情况下是singletom的 2、真是的案例 3、"使用Spring和ACEGI"---好像ACEGI是现在spring的子项目哦... ... |
|
返回顶楼 | |
发表时间:2006-12-23
lighter 写道 刚刚看了一下,挑一点小刺:
1、默认情况下是singletom的 2、真是的案例 3、"使用Spring和ACEGI"---好像ACEGI是现在spring的子项目哦... ... 谢谢提醒,昨天发现的问题,马上就记录下来了,可能写的有点快,敲错了 |
|
返回顶楼 | |
发表时间:2006-12-23
Spring建议以singleton方式注入的依赖尽量是stateless的
|
|
返回顶楼 | |
发表时间:2006-12-23
可以修改配置文件,修改参数吧!!
|
|
返回顶楼 | |
发表时间:2006-12-23
用 ThreadLocal 来保存用户信息
|
|
返回顶楼 | |
发表时间:2006-12-23
这不是Spring 的问题,跟本问题要搞清楚,
public class SomeServece extends BaseService implements SomeInterFace { private UserInfo user = super.getUserInfo(); public someMethod() { int userID = this.user.getUserID(); String userName = this.user.getUserName(); //bla bla do something user userID and userNaem } } 不能在service类里面写这种东西。居然有人说要用ThreadLocal...无语。 |
|
返回顶楼 | |
发表时间:2006-12-23
tiyi 写道 用 ThreadLocal 来保存用户信息
SecurityContext本身就是用ThreadLocal实现的,再来个ThreadLocal? |
|
返回顶楼 | |
发表时间:2006-12-23
ecsun 写道 改改配置,写个全局变量,什么问题也就解决了,哪有这么麻烦
用全局变量来解决? |
|
返回顶楼 | |
发表时间:2006-12-23
Godlikeme 写道 这不是Spring 的问题,跟本问题要搞清楚,
public class SomeServece extends BaseService implements SomeInterFace { private UserInfo user = super.getUserInfo(); public someMethod() { int userID = this.user.getUserID(); String userName = this.user.getUserName(); //bla bla do something user userID and userNaem } } 不能在service类里面写这种东西。居然有人说要用ThreadLocal...无语。 没看明白你的意思! 用ThreadLocal存当前用户很奇怪吗? |
|
返回顶楼 | |