上回说到, spring组件的注解Scope大约有singleton、prototype、request、session、global session 这么几种常用的场景。这里需要特别说明一下,根据源代码显示 Scope注解分为ConfigurableBeanFactory和WebApplicationContext两个大类,ConfigurableBeanFactory包含(singleton、prototype)两种Scope,WebApplicationContext下面有(ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,request,session,application,servletContext,contextParameters,contextAttributes)这么几种Scope。今天的示例重点是对request,session两个场景进行一次测试。

那在谈到具体的示例前,我先分享下对这两种场景的使用心得,以便与各位看官进行思想上的神交! 我们都知道B/S站点运行起来后,是一个多线程的运行环境。每个客户端登录都会产生一个session会话,它的生命周期 从登录系统到 session过期,期间session上存储的信息都是有效可用的,我习惯于叫它会话级的缓存,像用户登录的身份信息我们一般都会绑定到这个session上。这里我们要讲的@Scope("session"),就是spring提供出来的一个会话级bean方案,在这种模式下,用spring的DI功能来获取组件,可以做到在会话的生命周期中这个组件只有一个实例。接下来再说请求(request),http协议的处理模型,从客户端发起request请求,到服务端的处理,最后response给客户端,我们称为一次完整的请求。在这样的一次请求过程中,我们的服务站可能要串行调用funcA->funcB->funcC·... 这样的一串函数,假如我们的系统需要做细致的权限校验(用户权限,数据权限),更可怕的是funcA,funcB,funcC是3个人分别实现的,而且都要做权限校验。那么极有可能会出现3个人各连接了一次数据库,读取了同一批权限数据。这里想象一下,假如一个数据读取要花2秒,那么3个方法就要花费6秒的处理时间。但实际上这些数据只用在这个请求过程中读取一次,缓存在request上下文环境中,我习惯称之为线程级缓存。关于线程级缓存java有ThreadLocal方案,像Hibernate的事务就是用这种方案维持一次执行过程中数据库连接的唯一。当然,今天要讲的@Scope("request")也可以做到这种线程级别的缓存。下面我们看看具体的测试示例

  实现测试步骤说明:

1、创建一个@Scope("session")标注的Bean组件。关于proxyMode这个参数,是为了解决依存的会话或者请求上下文环境还没有时,自动装载组件报错,这里交给JDK代理,可以保证环境准备就绪时再执行组件装载。

@Component
//@Scope(value=WebApplicationContext.SCOPE_SESSION)
@Scope(value=WebApplicationContext.SCOPE_SESSION,proxyMode=ScopedProxyMode.INTERFACES)
public class SessionBean implements ISessionBean {
private UUID uuid;
public SessionBean(){
uuid = UUID.randomUUID();
}
public void printId(){
System.out.println("SessionBean:"+uuid);
}
}

2、创建一个@Scope("request")标注的Bean组件

@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST,proxyMode= ScopedProxyMode.INTERFACES)
public class RequestBean implements IRequestBean {
private UUID uuid; public RequestBean() {
uuid = UUID.randomUUID();
} public void printId() {
System.out.println("RequestBean:" + uuid);
}
}

3、添加一个多例的组件自动组装服务类,方便获取session、request组件。

@Service
@Scope(value=ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class BeanInstance {
@Autowired
private IRequestBean requestBean;
@Autowired
private ISessionBean sessionBean;
public IRequestBean getRequestBean() {
return requestBean;
}
public ISessionBean getSessionBean() {
return sessionBean;
}
}

4、添加测试代码

@Controller
@RequestMapping("/user")
// 添加session信息的注解,可以实现 session信息与map的映射 赋值
@SessionAttributes("user")
public class UserController {
@Autowired
private BeanInstance beanInstance1;
@Autowired
private BeanInstance beanInstance2; @RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(String name, Model model, HttpServletRequest request, HttpSession session) {
model.addAttribute("user", name);
System.out.println("SessionBean-1");
beanInstance1.getSessionBean().printId();
System.out.println("SessionBean-2");
beanInstance2.getSessionBean().printId();
System.out.println("RequestBean-1");
beanInstance1.getRequestBean().printId();
System.out.println("RequestBean-2");
beanInstance2.getRequestBean().printId();
return "user/check";
}
/**
* 检查自动装载的信息
* @param model
* @param request
* @param session
* @return
*/
@RequestMapping(value = "/check", method = RequestMethod.GET)
public String check(Model model, HttpServletRequest request, HttpSession session) {
System.out.println("SessionBean-1");
beanInstance1.getSessionBean().printId();
System.out.println("SessionBean-2");
beanInstance2.getSessionBean().printId();
System.out.println("RequestBean-1");
beanInstance1.getRequestBean().printId();
System.out.println("RequestBean-2");
beanInstance2.getRequestBean().printId();
return "user/check";
}
}

5、先发起一次登录请求,再发起一次登录后的检查请求。从打印的测试结果可以看到两次请求 拿到的session组件,其对应的ID都是相同的,所以在同一个会话中,session组件是唯一的。而request组件,在同一个request请求过程中,调用两次都得到同一个组件ID,而在第二次请求中request组件的ID改变了。因此正如上面所说,@Scope("request")模式在同一请求过程中,spring返回的组件也是唯一的,我们可以用这个方案来做线程级别的数据缓存。

参考资料

https://www.cnblogs.com/waytofall/p/3460533.html
https://www.cnblogs.com/lonecloud/p/5937513.html

spring 组件@Scope(request,session)示例的更多相关文章

  1. 终于搞懂Spring中Scope为Request和Session的Bean了

    之前只是很模糊的知道其意思,在request scope中,每个request创建一个新的bean,在session scope中,同一session中的bean都是一样的 但是不知道怎么用代码去验证 ...

  2. 【Spring】Spring IOC原理及源码解析之scope=request、session

    一.容器 1. 容器 抛出一个议点:BeanFactory是IOC容器,而ApplicationContex则是Spring容器. 什么是容器?Collection和Container这两个单词都有存 ...

  3. [Java][web]利用Spring随时随地获得Request和Session

    利用Spring随时随地获得Request和Session 一.准备工作: 在web.xml中加入 <listener> <listener-class> org.spring ...

  4. (转)Spring Bean Scope 有状态的Bean 无状态的Bean

    有状态会话bean   :每个用户有自己特有的一个实例,在用户的生存期内,bean保持了用户的信息,即“有状态”:一旦用户灭亡(调用结束或实例结束),bean的生命期也告结束.即每个用户最初都会得到一 ...

  5. Spring中获取request的几种方法,及其线程安全性分析

    前言 本文将介绍在Spring MVC开发的web系统中,获取request对象的几种方法,并讨论其线程安全性. 原创不易,如果觉得文章对你有帮助,欢迎点赞.评论.文章有疏漏之处,欢迎批评指正. 欢迎 ...

  6. [No000016E]Spring 中获取 request 的几种方法,及其线程安全性分析

    前言 本文将介绍在Spring MVC开发的web系统中,获取request对象的几种方法,并讨论其线程安全性. 原创不易,如果觉得文章对你有帮助,欢迎点赞.评论.文章有疏漏之处,欢迎批评指正. 欢迎 ...

  7. Spring中获取request的几种方法,及其线程安全性分析(山东数漫江湖)

    前言 本文将介绍在Spring MVC开发的web系统中,获取request对象的几种方法,并讨论其线程安全性. 原创不易,如果觉得文章对你有帮助,欢迎点赞.评论.文章有疏漏之处,欢迎批评指正. 欢迎 ...

  8. Spring中scope作用域

    scope作用域: 1.prototype 2.request      3.session 4.singleton 5.global session 1.prototype(多例) prototyp ...

  9. scope='request'的bean预加载冲突

    Error creating bean with name 'authenticationSuccessServlet': Scope 'request' is not active for the ...

随机推荐

  1. eclipse导入项目之后有感叹号

    说明项目的编译过程报错.导致原因:项目引入后,需要重新配置jar包路径. 1.右击你的项目-->Build Path-->Configure Build Path.... 2.在弹出的对话 ...

  2. excel去除空格

    =SUBSTITUTE(Sheet1!A1," ","") 在sheet2中输入上述公式,然后再通过拖拽复制公式,即可以很快的将sheet1中的数据全部处理.

  3. js 原型规则与示例

    五大规则 1. 所有的引用类型( 数组 对象 函数 ) 都是 具有对象特性即自由拓展属性 (除了 "null")意外 2. 所有的引用类型(数组 对象 函数 ) 都有一个 prot ...

  4. Spring MVC 用post方式提交表单到Controller乱码问题,而get方式提交没有乱码问题

    在web.xml中添加一个filter,即可解决post提交到Spring MVC乱码问题 <!-- 配置请求过滤器,编码格式设为UTF-8,避免中文乱码--> <filter> ...

  5. 浏览器http的缓存机制

    原文出处-----分享从伯乐在线看到的一篇好文章  http://web.jobbole.com/85509/ 针对浏览器的http缓存的分析也算是老生常谈了,每隔一段时间就会冒出一篇不错的文章,其原 ...

  6. Python 字符串大小写操作

    #coding=utf-8 #python中字符串的操作 # 字符串的大小写 s='hello_wOrld_oF_you' upper_str = s.upper() print('全部大写: ',u ...

  7. editplus和ultraedit(UE)的使用

    本来呢我是没有打算写关于editplus和ue的文章的,但是最近我花了12K买了一台电脑,在折腾电脑的时候就重新设置了好多经常用到的工具,以前我使用比较多的是editplus,但是使用这个editpl ...

  8. js执行函数报错Cannot set property 'value' of null怎么解决?

    js执行函数报错Cannot set property 'value' of null 的解决方案: 原因:dom还没有完全加载 第一步:所以js建议放在body下面执行, 第二步:window.on ...

  9. Linux常用命令(二)--文件目录命令

    1. 列表目录命令: 格式: ls [参数] 用于显示文件或目录信息 选项: -l 每行显示一个文件和目录信息(长格式),简写:ll等同于ls -l 注意:当参数是文件时,显示此文件全部信息 当参数是 ...

  10. 支付sdk —— 该组件为封装了 微信,支付宝,银联支付

    [精品]  支付组件 简要说明该组件为封装了 微信,支付宝,银联支付, 一键快速集成,几行代码即可集成 微信,支付宝,银联支付. ## 示例: # 测试账号:1.银联支付:提供测试使用卡号.手机号信息 ...