为什么直接通过 @Autowired 注入的 HttpServletRequest 没有线程安全的问题

简介: 我们在各个地方注入依赖时,大多数情况下都是单例的。为什么直接通过 @Autowired 注入的 HttpServletRequest 没有线程安全的问题呢?带着这个问题我做了如下笔记。

SpringBoot 启动过程中很重要的一步就是刷新上下文

org.springframework.boot.SpringApplication#refreshContext
org.springframework.context.support.AbstractApplicationContext#postProcessBeanFactory

Web 应用的上下文主要由WebApplicationContextUtils工具类来负责,在下面的方法中

org.springframework.web.context.support.WebApplicationContextUtils#registerWebApplicationScopes(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, javax.servlet.ServletContext)

其中就对DefaultListableBeanFactory注册了ServletRequest的依赖处理

beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory());
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;
}
    public static RequestAttributes getRequestAttributes() {
   
        RequestAttributes attributes = requestAttributesHolder.get();
        if (attributes == null) {
   
            attributes = inheritableRequestAttributesHolder.get();
        }
        return attributes;
    }
    private static final ThreadLocal<RequestAttributes> requestAttributesHolder =
            new NamedThreadLocal<RequestAttributes>("Request attributes");

每次请求都会经过

org.springframework.web.filter.RequestContextFilter

其中会设置

    @Override
    protected void doFilterInternal(
            HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
   

        ServletRequestAttributes attributes = new ServletRequestAttributes(request, response);
        initContextHolders(request, attributes);

        try {
   
            filterChain.doFilter(request, response);
        }
        finally {
   
            resetContextHolders();
            if (logger.isDebugEnabled()) {
   
                logger.debug("Cleared thread-bound request context: " + request);
            }
            attributes.requestCompleted();
        }
    }

    private void initContextHolders(HttpServletRequest request, ServletRequestAttributes requestAttributes) {
   
        LocaleContextHolder.setLocale(request.getLocale(), this.threadContextInheritable);
        RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable);
        if (logger.isDebugEnabled()) {
   
            logger.debug("Bound request context to thread: " + request);
        }
    }

    private void resetContextHolders() {
   
        LocaleContextHolder.resetLocaleContext();
        RequestContextHolder.resetRequestAttributes();
    }
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency
目录
相关文章
|
6月前
|
容器
多线程时Autowired自动注入问题
多线程时Autowired自动注入问题
206 2
|
Java Spring
Spring在多线程中bean的注入问题
Spring在多线程中bean的注入问题
159 0
|
网络协议 安全 API
驱动开发:内核远程线程实现DLL注入
在笔者上一篇文章`《内核RIP劫持实现DLL注入》`介绍了通过劫持RIP指针控制程序执行流实现插入DLL的目的,本章将继续探索全新的注入方式,通过`NtCreateThreadEx`这个内核函数实现注入DLL的目的,需要注意的是该函数在微软系统中未被导出使用时需要首先得到该函数的入口地址,`NtCreateThreadEx`函数最终会调用`ZwCreateThread`,本章在寻找函数的方式上有所不同,前一章通过内存定位的方法得到所需地址,本章则是通过解析导出表实现。
4944 0
|
Shell
驱动开发:内核ShellCode线程注入
还记得`《驱动开发:内核LoadLibrary实现DLL注入》`中所使用的注入技术吗,我们通过`RtlCreateUserThread`函数调用实现了注入DLL到应用层并执行,本章将继续探索一个简单的问题,如何注入`ShellCode`代码实现反弹Shell,这里需要注意一般情况下`RtlCreateUserThread`需要传入两个最重要的参数,一个是`StartAddress`开始执行的内存块,另一个是`StartParameter`传入内存块的变量列表,而如果将`StartParameter`地址填充为`NULL`则表明不传递任何参数,也就是只在线程中执行`ShellCode`代码,利用
379 1
|
Windows
突破SESSION 0 隔离的远线程注入
在Windows XP,Windows Server 2003以及更早的版本中,第一个登录的用户以及Windows的所有服务都运行在Session 0上,这样的做法导致用户使用的应用程序可能会利用Windows的服务程序提升自身的权限,为此,在后续的Windows版本中,引入了一种隔离机制,普通应用程序已经不再session 0中运行。
156 0
|
前端开发 安全 Java
Spring注入的成员属性HttpServletRequest是线程安全的吗?【享学Spring MVC】(上)
Spring注入的成员属性HttpServletRequest是线程安全的吗?【享学Spring MVC】(上)
|
XML 安全 前端开发
Spring注入的成员属性HttpServletRequest是线程安全的吗?【享学Spring MVC】(下)
Spring注入的成员属性HttpServletRequest是线程安全的吗?【享学Spring MVC】(下)
Spring注入的成员属性HttpServletRequest是线程安全的吗?【享学Spring MVC】(下)
|
安全 API Go
我的免杀之路:远程线程注入
远程线程注入技术能实现在Windows系统下进程的隐藏。其主要核心在于一个Windows API函数CreateRemoteThread,通过它可以在另外一个进程中注入一个线程并执行。
1032 0
我的免杀之路:远程线程注入
|
Java Linux Android开发
【Android 逆向】Android 进程注入工具开发 ( 远程进程注入动态库文件操作 | 注入动态库 加载 业务动态库 | 业务动态库启动 | pthread_create 线程开发 )
【Android 逆向】Android 进程注入工具开发 ( 远程进程注入动态库文件操作 | 注入动态库 加载 业务动态库 | 业务动态库启动 | pthread_create 线程开发 )
197 0