网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > Java
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
本月文章推荐
.用SWING组件实现登录对话框.
.用Java绘制K线图.
.Spring IDE 1.2.4发布.
.Java技巧:用Java实现回调例程.
.BEA邮政行业RFID解决方案.
.java线程简介(无处不在的线程).
.比尔学Java:Java Socket篇.
.动态Proxy与Java ACL用户访问控制.
.错误的堆大小产生的“堆问题”.
.破除Java神话之三.
.教您如何成为 EJB 专家详解系列连.
.WWW访问传统客户/服务器应用的方.
.Java.util包简介 如何开发应用之.
.getYear 方法.
.EJB查询语言.
.大道至简 Java 23种模式一点就通.
.Java框架:初学者对Hibernate的学.
.关于线程的讲解(出自Java原著).
.设计模式研究--Proxy Model.
.Java嵌入式开发之四.

Spring Singleton的陷阱

发表日期:2008-2-14


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

我还看好它的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  
    }
}

上一篇:java的设计模式,学习心得总结 人气:1081
下一篇:Java中用Robot类控制鼠标和键盘的方法 人气:1200
浏览全部Spring Singleton的内容 Dreamweaver插件下载 网页广告代码 祝你圣诞节快乐 2009年新年快乐