@Autowired HttpSession & HttpServletRequest原理

原文地址 (我的个人网站,欢迎访问):
@Autowired HttpSession & HttpServletRequest原理

问题

在开发Controller的时候,经常会需要使用到HttpSessionHttpServletRequest这两个接口的实例对象。在工作室中的项目,无论是师兄留下的代码还是自己编写,基本都是使用比较简单的,就是直接从方法参数中获取,就像下面这样:

@RequestMapping("/test") //@RestController省略@ResponseBody注解
public ResponseModel doTest(HttpSession session) throws MissingServletRequestParameterException {
        return ResponseModel.ok().body(session.getId());
}

这不失为一个好办法,但也有缺点:一是如果多个方法需要会话操作(如权限接口)的话会显得冗余,而是加长了方法参数列表降低了代码可读性。毕竟Controller中的方法一般都会代表前台某个参数。所以我想寻求一种更好的办法。Spring的依赖注入很方便,那么,Session和Request对象能不能依赖注入呢?

只有一年多开发经验的我,一开始当然以为是不行的。

因为Session和Request的生命周期是会话级别和请求级别,而对Session、Request进行依赖注入的对象是Controller,是单例对象。我们都知道,某个对象依赖注入一个生命周期不如自己长的对象,最后的结果是被注入的对象生命周期变得和注入的对象生命周期一样长。假如有两个不同类的实例A和B,A这种持有B的引用,B注入进A的引用里,那么在A生命周期结束前Spring不会再去新注入B对象,如果A是单例对象,B定义为prototype,那么实例B也会“变成”单例,鸡犬升天。这显然违背我们把B定义为非单例的初衷。另外,在Webx3 开发文档 4.4.2 中也说明原生Spring注入无法满足这种情况,Webx通过<request-contexts>增强以后,Webx Turbine才可以使用@Autowired注入。也让我一开始对“Spring无法注入Session”深信不疑。

直到我网上搜到一些所谓获取session方法大全博客,里面赫然有着autowired注入这种方法。

这 ..

不是说原生Spring不可以吗webx爸爸 ..
于是默默的写了一大堆测试代码,找了很多文档资料,最终搞明白了其中的道理,分享如下。先把结果写出来,如果有兴趣可以再往下看测试代码。

Scoped Proxy

简单介绍一个Spring对单例对象注入非单例实例的一个解决方案:Scoped Proxy.

Scoped proxy使用代理模式,不去直接注入这个类的实例,而是每次使用的时候都去创建一个代理对象,当调用注入方法时,会通过其他途径去调用原生对象的方法。所以我们autowired的时候不是真的注入自己的对象,只是一个壳而已。

自己使用bean scoped的例子可以查看开发文档:Spring4 开发文档: bean scope
简洁的解释可以看:spring scoped proxy bean

结论

知道了Scoped Proxy,想必对这个的实现也了解的差不多了。Spring巧妙地注入了一个装饰器代理了真实对象的操作,只在需要的时候获取真实的Request和Session对象,获取方法Servlet自身实现好了,和Servlet类获取Request和Session应该大同小异。所以获取Session和Request的几种方法中:

  • @Autowired获取到的是装饰器对象
  • 方法参数获取到的是真实对象
  • 无论是@Autowired还是方法参数的request,request.getSession()获取到的是真实Session对象

shiro session

实际测试中,发现整合Shiro以后HttpSession的差异。

虽然都是注入了一个装饰器对象,但是Spring中,无论是装饰器调用的,还是方法参数获取到的,或者是request.getSession()获取到的HttpSession都是真实的HttpSession对象,hashCode都是不变的,非分布式的单服务器实例下,一个会话只有一个HttpSession

整合Shiro以后,无论是装饰器调用的,还是方法参数获取到的,或者是request.getSession()获取到的HttpSession都是代理对象,每次获取到的session,只是"看上去"和真实Session一样,实际上每次执行controller获取到的session都是不同的实例,hashcode是不一样的。

这是因为整合Shiro以后,StoppingAwareProxiedSession继承了原来的HttpSession实现类(Tomcat中是StandardSession),属于shiro自定义的session的子类。通过这个代理对象的源码,所有与session相关的方法都是通过它内部委托类delegate进行的,而到delegate的类型其实也是 org.apache.catalina.session.StandardSessionFacade ,也就是说,两者在操作session时,都是用同一个类型的session。

Shiro用了一层代理来包装HttpSessionHttpServletRequest这两个接口实例,如果用@Autowired注入,算上@Autowired的装饰器,是两层代理。

Shiro包装HttpSession

测试

测试demo和测试数据见:

我的github

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,265评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,274评论 1 288
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,087评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,479评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,782评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,218评论 1 207
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,594评论 2 309
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,316评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,955评论 1 237
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,274评论 2 240
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,803评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,177评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,732评论 3 229
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,953评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,687评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,263评论 2 267
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,189评论 2 258

推荐阅读更多精彩内容