【Spring】 Bean 注入 HttpServletRequest 能保证线程安全的原理

文章目录

    • 前言
    • [1. 图示](#1. 图示)
    • [2. 源码坐标](#2. 源码坐标)
    • 后记

前言

今天看了一段老业务代码,HttpServletRequest 被注入后直接用于业务逻辑。

好奇Spring是如何解决线程安全问题。

java 复制代码
@Controller
public class TestController {

    @Resource
    HttpServletRequest request;
    
    @ResponseBody
    @GetMapping("/test")
    public String test() {
        return request.getQueryString();
    }
}

本质问题是 Spring 如何装配 Controller 中 HttpServletRequest 的bean依赖

1. 图示

2. 源码坐标

可以在代码层面打断点验证,版本:SpringBoot 2.7.5 (自行集成WebStarter)

  • 加载web相关的bean定义
java 复制代码
ServletWebServerApplicationContext.java:141
  • 设置工厂
java 复制代码
WebApplicationContextUtils#registerWebApplicationScopes(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, javax.servlet.ServletContext)
  • 具体的工厂方法定义(定义是从线程中取request)
java 复制代码
RequestObjectFactory#getObject
java 复制代码
// 关键代码块
@Override
public ServletRequest getObject() {
	return currentRequestAttributes().getRequest();
}
  • 启动时解析依赖,将工厂方法植入
java 复制代码
org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency
org.springframework.beans.factory.support.DefaultListableBeanFactory#findAutowireCandidates
org.springframework.beans.factory.support.AutowireUtils#resolveAutowiringValue
  • 接收请求
java 复制代码
FrameworkServlet.java:1003  将响应放在ThreadLocal中
java 复制代码
// 关键代码块
if (requestAttributes != null) {
	RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable);
}
  • 回调工厂方法创建 Request
java 复制代码
AutowireUtils.java:292
java 复制代码
// 关键代码
return method.invoke(this.objectFactory.getObject(), args)

后记

  • 解决 HttpServletRequest 的线程安全问题的思路
    • 工厂方法定义, 将 Request 的创建约束为从 ThreadLocal 中取。
    • 收到请求 ,将 Request 放入ThreadLocal 中。(请求时设置 Request)
    • Controller 实例化,使用动态代理技术回调工厂方法。(业务逻辑消费 Request)

  • 建议按官方建议替换成方法参数,语义更加清晰。
java 复制代码
    @ResponseBody
    @GetMapping("/test")
    public String test(HttpServletRequest request) {
        return request.getQueryString();
    }
相关推荐
小江的记录本3 分钟前
【Transformer架构】Transformer架构核心知识体系(包括自注意力机制、多头注意力、Encoder-Decoder结构)
java·人工智能·后端·python·深度学习·架构·transformer
小松加哲9 分钟前
深入剖析Tomcat原理
java·tomcat
三原31 分钟前
附源码:三原管理系统新增俩种常用布局
java·前端·vue.js
gelald32 分钟前
SpringBoot - 配置加载
spring boot·后端·spring
現実君37 分钟前
现代化嵌入式AI编程-IDEA指南
java·intellij-idea·ai编程
Java面试题总结40 分钟前
2026年Java面试题最新整理,附白话答案
java·开发语言·jvm·笔记·spring·intellij-idea
芒果披萨1 小时前
日志管理 logging
java·开发语言·c++
高冷的上官梓芸1 小时前
【A15】默认关闭屏保
java
爱学习的小囧1 小时前
嵌套式 ESXi 8.x/9.0 虚拟设备下载与实战指南
java·linux·运维·服务器·虚拟化
五阿哥永琪1 小时前
从零读懂 Java 函数式接口:Function、Consumer、Supplier、Predicate
java·开发语言