spring 组件Scope(request,session)示例

上回说到, 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");
        beanInstance1.getSessionBean().printId();
        System.out.println("RequestBean-1");
        beanInstance2.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");
        beanInstance1.getSessionBean().printId();
        System.out.println("RequestBean-1");
        beanInstance2.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

时间: 2024-11-13 01:36:59

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

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

一.容器 1. 容器 抛出一个议点:BeanFactory是IOC容器,而ApplicationContex则是Spring容器. 什么是容器?Collection和Container这两个单词都有存放什么东西的意思,但是放在程序猿的世界,却注定是千差万别.Collection,集合,存放obj instanceof Class为true的一类对象,重点在于存放:Container,容器,可以存放各种各样的obj,但不仅仅是存放,他被称为容器,更重要的是他能管理存放对象的生命周期和依赖. 容器:

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

利用Spring随时随地获得Request和Session 一.准备工作: 在web.xml中添加 <listener> <listener-class> org.springframework.web.context.request.RequestContextListener </listener-class> </listener> 二.使用方法: 1.方法一:通过代码实现 HttpServletRequest request = ((ServletR

spring中scope作用域(转)

摘自 http://www.cnblogs.com/qq78292959/p/3716827.html 今天研究了一下scope的作用域.默认是单例模式,即scope="singleton".另外scope还有prototype.request.session.global session作用域.scope="prototype"多例.再配置bean的作用域时,它的头文件形式如下: 如何使用spring的作用域: <bean id="role&quo

spring中scope(作用越)理解

今天总结了一下spring中作用域scope的用法.在spring中作用域通过配置文件形式的用法如下. <bean id="role" class="spring.chapter2.maryGame.Role" scope="singleton"/> 一. 在spring 中常用的作用域有单例模式(singleton),和多例模式(prototype) 1.当一个bean的 作用域设置为singleton, 那么Spring IOC容

Spring 作用域 scope

spring的作用域将对Bean的生命周期和创建方式产生影响.  主要分为五种类型的作用域 singleton (默认)在spring IOC容器中仅存在一个Bean实例,Bean以单实例的方式存在. prototype 每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行new XxxBean()的操作. request 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于webApplicationContext环境. session 同一个HTT

Spring Bean Scope

In Spring, bean scope is used to decide which type of bean instance should be return from Spring container back to the caller. 5 types of bean scopes supported : singleton – Return a single bean instance per Spring IoC container prototype – Return a

spring之scope作用域

spring中,bean的作用域有五种类型:默认是单例模式,         singleton         prototype         request         session         global session 配置作用域时,使用 scope属性,xml文件配置如下, 查看spring官方文档,解释如下: 1.singleton     如果一个bean配置为singelton,表示该bean在spring IOC容器中只有一个实例,也就是单例 配置如下:下面两种

Spring Bean Scope 有状态的Bean 无状态的Bean

http://blog.csdn.net/anyoneking/article/details/5182164 在Spring的Bean配置中,存在这样两种情况: [xhtml] view plaincopy <bean id="testManager" class="com.sw.TestManagerImpl" scope="singleton" /> <bean id="testManager" cla

spring boot + redis 实现session共享

这次带来的是spring boot + redis 实现session共享的教程. 在spring boot的文档中,告诉我们添加@EnableRedisHttpSession来开启spring session支持,配置如下: @Configuration @EnableRedisHttpSession public class RedisSessionConfig { } 而@EnableRedisHttpSession这个注解是由spring-session-data-redis提供的,所以