java

位置:IT落伍者 >> java >> 浏览文章

Spring Singleton的陷阱介绍


发布日期:2018年03月27日
 
Spring Singleton的陷阱介绍

这是一个真实的案例我们在项目中使用Spring和ACEGI我之所以选择ACEGI除了它对权限的良好控制外

我还看好它的SecurityContextHolder通过代码 Authentication auth = SecurityContextHoldergetContext()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 = SecurityContextHoldergetContext()getAuthentication()

return (UserContext) authgetPrincipal()

}

这样在其他的Service和Dao类里可以通过 supergetUserContext() supergetUserInfo()

来得到用户的信息这也为问题的产生提供了温床请看如下代码 public class SomeServece extends BaseService implements SomeInterFace

……{

private UserInfo user = supergetUserInfo()

public someMethod()

……{

int userID = thisusergetUserID()

String userName = thisusergetUserName()

//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 = supergetUserInfo()getUserID()

String userName = supergetUserInfo()getUserName()

//bla bla do something user userID and userNaem

}

}

上一篇:Hibernate只查询部分/指定字段

下一篇:名词解释 什么是Struts?