@Autowired HttpServletRequest之所以线程安全是因为, httpsevletRequest 储存在 RequestContextHolder中。

  • 每次http请求的doXXX 都会被FrameworkServlet拦截,通过 RequestContextHolder.setxxxxx  写入TheadLocal。
  • Autowired 获取request的时候,通过RequestContextHolder.getxxx 从ThreadLocal中获取。

为什么Autowired HttpServletRequest是线程安全的,获取的方式

1. 启动断点调试,查看request的来源是  WebApplicationContextUtils.RequestObjectFactory.

2. 查看源码 WebApplicationContextUtils.RequestObjectFactory, request 来自于 RequestContextHolder.currentRequestAttributes() 方法

class WebApplicationContextUtils {
@SuppressWarnings("serial")
private static class RequestObjectFactory implements ObjectFactory<ServletRequest>, Serializable { @Override
public ServletRequest getObject() {
return currentRequestAttributes().getRequest();
} @Override
public String toString() {
return "Current HttpServletRequest";
}
}
    private static ServletRequestAttributes currentRequestAttributes() {
RequestAttributes requestAttr = RequestContextHolder.currentRequestAttributes();
if (!(requestAttr instanceof ServletRequestAttributes)) {
throw new IllegalStateException("Current request is not a servlet request");
}
return (ServletRequestAttributes) requestAttr;
}
}

3. 上述方法的attributes来自于线程安全的ThreadLocal中的当前线程的HttpServletRequest

public abstract class RequestContextHolder  {

    private static final boolean jsfPresent =
ClassUtils.isPresent("javax.faces.context.FacesContext", RequestContextHolder.class.getClassLoader()); private static final ThreadLocal<RequestAttributes> requestAttributesHolder =
new NamedThreadLocal<>("Request attributes");
    public static void setRequestAttributes(@Nullable RequestAttributes attributes, boolean inheritable) {
if (attributes == null) {
resetRequestAttributes();
}
else {
if (inheritable) {
inheritableRequestAttributesHolder.set(attributes);
requestAttributesHolder.remove();
}
else {
requestAttributesHolder.set(attributes);
inheritableRequestAttributesHolder.remove();
}
}
}

设置的方式

request是什么时候设置到threadlocal中去的呢? 是在Springmvc的dispatcherServlet的父类FrameworkServlet里操作的.。 doGet 、doPost 、doXXX方法都是委托processRequest方法去做的. 也就是说请求方法会被FrameworkServlet的processRequest拦截。

class FrameworkServlet {
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
.....
initContextHolders(request, localeContext, requestAttributes);
} private void initContextHolders(HttpServletRequest request,
@Nullable LocaleContext localeContext, @Nullable RequestAttributes requestAttributes) { ......
if (requestAttributes != null) {
RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable);
}
....
} }

参考

https://www.cnblogs.com/abcwt112/p/7777258.html

Spring 单例 httprequest 线程安全的更多相关文章

  1. Spring单例与线程安全小结

    一.Spring单例模式与线程安全   Spring框架里的bean,或者说组件,获取实例的时候都是默认的单例模式,这是在多线程开发的时候要尤其注意的地方. 单例模式的意思就是只有一个实例.单例模式确 ...

  2. Spring单例Bean和线程安全

    Spring的bean默认都是单例的,这些单例Bean在多线程程序下如何保证线程安全呢?例如对于Web应用来说,Web容器对于每个用户请求都创建一个单独的Sevlet线程来处理请求,引入Spring框 ...

  3. 002-创建型-03-单例模式(Singleton)【7种】、spring单例及原理

    一.概述 保证一个类仅有一个实例,并提供一个全局访问点 私有构造器.线程安全.延迟加载.序列化和反序列化安全.反射攻击 1.1.适用场景 1.在多个线程之间,比如servlet环境,共享同一个资源或者 ...

  4. Spring单例 和 Scope注解

    关键字  @Scope  @Qualifier  Singleton 单例 Spring是单例模式.结合Springboot的例子. Controller @Autowired private Tes ...

  5. 【转】Spring Bean单例与线程安全

    一.Spring单例模式及线程安全 Spring框架中的Bean,或者说组件,获取实例的时候都是默认单例模式,这是在多线程开发的时候需要尤其注意的地方. 单例模式的意思是只有一个实例,例如在Sprin ...

  6. Spring Bean单例与线程安全

    一.Spring单例模式及线程安全 Spring框架中的Bean,或者说组件,获取实例的时候都是默认单例模式,这是在多线程开发的时候需要尤其注意的地方. 单例模式的意思是只有一个实例,例如在Sprin ...

  7. Spring Controller单例与线程安全那些事儿

    目录 单例(siingleton)作用域 原型(Prototype)作用域 多个HTTP请求在Spring控制器内部串行还是并行执行方法? 实现单例模式并模拟大量并发请求,验证线程安全 附录:Spri ...

  8. (转载)spring单例和多例详解。如何在单例中调用多例对象

    spring生成对象默认是单例的.通过scope属性可以更改为多例. <bean id="user" class="modle.User" scope=& ...

  9. 有关线程安全的探讨--final、static、单例、线程安全

    我的代码中已经多次使用了线程,然后还非常喜欢使用据说是线程不安全的静态方法,然后又看到很多地方最容易提的问题就是这个东西线程不安全   于是我不免产生了以下几个亟待解决的问题: 什么样的代码是天生线程 ...

随机推荐

  1. 另类之将ipython notebook嵌入blog方法

    另类之将ipython notebook嵌入blog方法 ipynb文件很强大. 可是一直苦于没有找到好的方法把它直接嵌入到博文里. 现在得到一个另类的方法: 就是利用github集成了nbviewe ...

  2. 使用abcpdf将html转换成pdf文件

    ABCpdf.NET使用介绍 最新做一个项目需要生成pdf文档以供打印,研究决定使用abcpdf这款组件,先针对其使用方法做一个简单的总结介绍以给有需要的朋友做参考. 一. ABCpdf.NET简单介 ...

  3. mysql 距离函数

    要有超级权限 SET GLOBAL log_bin_trust_function_creators = 1;DELIMITER $$CREATE DEFINER=`root`@`localhost` ...

  4. sql server中的日期函数

    DATEADD   在向指定日期加上一段时间的基础上,返回新的 datetime 值. 语法           DATEADD ( datepart , number, date ) 参数 (1) ...

  5. ubuntun16.04+cuda9.0+cudnn7+anaconda3+pytorch+anaconda3下py2安装pytorch

    一.电脑配置 说明: 电脑配置: LEGION笔记本CPU Inter Core i7 8代GPU NVIDIA GeForce GTX1060Windows10 所需的环境: Anaconda3(6 ...

  6. OpenCV 用二进制位表示 type & channels 的方式

    OpenCV 的类型与通道的表示方法. 参考文件 https://github.com/opencv/opencv/blob/05b15943d6a42c99e5f921b7dbaa8323f3c04 ...

  7. 利用反射型XSS二次注入绕过CSP form-action限制

    利用反射型XSS二次注入绕过CSP form-action限制 翻译:SecurityToolkit 0x01 简单介绍 CSP(Content-Security-Policy)是为了缓解XSS而存在 ...

  8. 【SVN】centos环境下搭建SVN服务器

    1.安装SVN,有些linux发行版自带SVN,可以用下面方法检测是否安装SVN. svn --version 如果 Subversion 客户端没有安装,命令将报告svn命令找不到的错误. 我们可以 ...

  9. 【codeforces】【比赛题解】#940 CF Round #466 (Div. 2)

    人生的大起大落莫过如此,下一场我一定要回紫. [A]Points on the line 题意: 一个直线上有\(n\)个点,要求去掉最少的点,使得最远两点距离不超过\(d\). 题解: 暴力两重fo ...

  10. 【bzoj题解】1001 狼抓兔子

    题目描述 现在小朋友们最喜欢"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:   ...