Spring 单例 httprequest 线程安全
@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 线程安全的更多相关文章
- Spring单例与线程安全小结
一.Spring单例模式与线程安全 Spring框架里的bean,或者说组件,获取实例的时候都是默认的单例模式,这是在多线程开发的时候要尤其注意的地方. 单例模式的意思就是只有一个实例.单例模式确 ...
- Spring单例Bean和线程安全
Spring的bean默认都是单例的,这些单例Bean在多线程程序下如何保证线程安全呢?例如对于Web应用来说,Web容器对于每个用户请求都创建一个单独的Sevlet线程来处理请求,引入Spring框 ...
- 002-创建型-03-单例模式(Singleton)【7种】、spring单例及原理
一.概述 保证一个类仅有一个实例,并提供一个全局访问点 私有构造器.线程安全.延迟加载.序列化和反序列化安全.反射攻击 1.1.适用场景 1.在多个线程之间,比如servlet环境,共享同一个资源或者 ...
- Spring单例 和 Scope注解
关键字 @Scope @Qualifier Singleton 单例 Spring是单例模式.结合Springboot的例子. Controller @Autowired private Tes ...
- 【转】Spring Bean单例与线程安全
一.Spring单例模式及线程安全 Spring框架中的Bean,或者说组件,获取实例的时候都是默认单例模式,这是在多线程开发的时候需要尤其注意的地方. 单例模式的意思是只有一个实例,例如在Sprin ...
- Spring Bean单例与线程安全
一.Spring单例模式及线程安全 Spring框架中的Bean,或者说组件,获取实例的时候都是默认单例模式,这是在多线程开发的时候需要尤其注意的地方. 单例模式的意思是只有一个实例,例如在Sprin ...
- Spring Controller单例与线程安全那些事儿
目录 单例(siingleton)作用域 原型(Prototype)作用域 多个HTTP请求在Spring控制器内部串行还是并行执行方法? 实现单例模式并模拟大量并发请求,验证线程安全 附录:Spri ...
- (转载)spring单例和多例详解。如何在单例中调用多例对象
spring生成对象默认是单例的.通过scope属性可以更改为多例. <bean id="user" class="modle.User" scope=& ...
- 有关线程安全的探讨--final、static、单例、线程安全
我的代码中已经多次使用了线程,然后还非常喜欢使用据说是线程不安全的静态方法,然后又看到很多地方最容易提的问题就是这个东西线程不安全 于是我不免产生了以下几个亟待解决的问题: 什么样的代码是天生线程 ...
随机推荐
- soj1011. Lenny's Lucky Lotto
1011. Lenny's Lucky Lotto Constraints Time Limit: 1 secs, Memory Limit: 32 MB Description Lenny like ...
- laravel带条件查询手动分页
后台php代码: //手动分页 $users = $kaoqin; //打算输出的数组,二维 $perPage = 10; if ($request->has('page')) { $curre ...
- Kafka消息系统基础知识索引
一些观念的修正 从 0.9 版本开始,Kafka 的标语已经从“一个高吞吐量,分布式的消息系统”改为"一个分布式流平台". Kafka不仅仅是一个队列,而且是一个存储,有超强的堆积 ...
- asp.net 调用post方法并获取返回值
/// <summary> /// http协议 post数据 接受返回结果 /// </summary> /// <param ...
- 2017 jq 总结
$(el).parent() 获取父级元素 .parents('th') 获取祖元素th .parentsUntil("th") 找到 ...
- JDk1.8源码StringBuffer
一.概念 StringBuffer A thread-safe, mutable sequence of characters. A string buffer is like a {@link St ...
- 并行运行多个python虚拟机
之前遇到一个问题,需要将场景服务这个模块拆分出来,用独立的一个线程去执行.使用独立的线程好处就是,逻辑写的可以相对简单粗暴点,不必考虑到大量的场景服务逻辑卡主线程的情况. 由于我们服务器之前是使用py ...
- LINUX的DNS设置【转】
网卡DNS设置 用windos系统大家都知道,本地连接里面有一个DNS设置. 那么这个选项对应Linux系统的话就是在网卡配置文件,通过编辑vi /etc/sysconfig/network-scr ...
- C# 链接webservice报错
未处理 System.ServiceModel.EndpointNotFoundException Message="没有终结点对可能接受消息的 http://192.168.0.168/ ...
- MVVM设计模式的事件绑定
为什么要事件绑定 这个问题其实是很好理解的,因为事件是丰富多样的,单纯的命令绑定远不能覆盖所有的事件.例如Button的命令绑定能够解决Click事件的需求,但Button的MouseEnter.窗体 ...