为什么直接通过 @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
目录
相关文章
|
容器
多线程时Autowired自动注入问题
多线程时Autowired自动注入问题
400 2
|
Java Spring
Spring在多线程中bean的注入问题
Spring在多线程中bean的注入问题
573 0
|
安全 API Go
我的免杀之路:远程线程注入
远程线程注入技术能实现在Windows系统下进程的隐藏。其主要核心在于一个Windows API函数CreateRemoteThread,通过它可以在另外一个进程中注入一个线程并执行。
1541 0
我的免杀之路:远程线程注入
|
Windows
突破SESSION 0 隔离的远线程注入
在Windows XP,Windows Server 2003以及更早的版本中,第一个登录的用户以及Windows的所有服务都运行在Session 0上,这样的做法导致用户使用的应用程序可能会利用Windows的服务程序提升自身的权限,为此,在后续的Windows版本中,引入了一种隔离机制,普通应用程序已经不再session 0中运行。
395 0
|
前端开发 安全 Java
Spring注入的成员属性HttpServletRequest是线程安全的吗?【享学Spring MVC】(上)
Spring注入的成员属性HttpServletRequest是线程安全的吗?【享学Spring MVC】(上)
|
XML 安全 前端开发
Spring注入的成员属性HttpServletRequest是线程安全的吗?【享学Spring MVC】(下)
Spring注入的成员属性HttpServletRequest是线程安全的吗?【享学Spring MVC】(下)
Spring注入的成员属性HttpServletRequest是线程安全的吗?【享学Spring MVC】(下)
|
Java Linux Android开发
【Android 逆向】Android 进程注入工具开发 ( 远程进程注入动态库文件操作 | 注入动态库 加载 业务动态库 | 业务动态库启动 | pthread_create 线程开发 )
【Android 逆向】Android 进程注入工具开发 ( 远程进程注入动态库文件操作 | 注入动态库 加载 业务动态库 | 业务动态库启动 | pthread_create 线程开发 )
347 0
|
SQL 前端开发 安全
SpringBoot项目使用多线程处理任务时无法通过Autowired注入bean
  最近在做一个“温湿度控制”的项目,项目要求通过用户设定的温湿度数值和实时采集到的数值进行比对分析,因为数据的对比与分析是一个通过前端页面控制的定时任务,经理要求在用户开启定时任务时,单独开启一个线程进行数据的对比分析,并将采集到的温湿度数值存入数据库中的历史数据表,按照我们正常的逻辑应该是用户在请求开启定时任务时,前端页面通过调用后端接口,创建一个新的线程来执行定时任务,然后在线程类中使用 @Autowired 注解注入保存历史数据的service层,在线程类中调用service层保存历史数据的方法实现温湿度数据的保存,这时就出现了一个很尴尬的问题,在新开启的线程中使用 @Autowire
509 0

热门文章

最新文章