当前位置: 首页 > 面试题库 >

ScopedProxy如何决定要使用的会话?

经和歌
2023-03-14
问题内容

Singleton无法自动装配SessionBean,而ScopedProxy可以。

假设在同一应用程序中同时有100个用户有一个有效的会话,那么ScopedProxy如何确定会话的含义?

我认为ScopedProxy不会选择任何随机会话,我认为这是无稽之谈。

  1. ScopedProxy如何决定要使用的会话?
  2. 如果0个用户拥有一个会话该怎么办?会NullPointerException发生吗?
  3. @Async是不同于调用Request-Processing-Thread的线程,如何将HttpRequest-Context注入到Async任务中?

问题答案:

ThreadLocal几乎就是您要寻找的答案。

此类提供线程局部变量。这些变量与普通变量不同,因为每个访问一个线程(通过其get或set方法)的线程都有其自己的,独立初始化的变量副本。

春天有RequestContextHolder

Holder类以线程绑定的RequestAttributes对象的形式公开Web请求。如果将Inheritable标志设置为true,则该请求将被当前线程产生的任何子线程继承。

在课程中,您将看到以下内容:

private static final ThreadLocal<RequestAttributes> requestAttributesHolder =
            new NamedThreadLocal<RequestAttributes>("Request attributes");

这是实际的setter(注意它是静态的):

/**
     * Bind the given RequestAttributes to the current thread.
     * @param attributes the RequestAttributes to expose,
     * or {@code null} to reset the thread-bound context
     * @param inheritable whether to expose the RequestAttributes as inheritable
     * for child threads (using an {@link InheritableThreadLocal})
     */
    public static void setRequestAttributes(RequestAttributes attributes, boolean inheritable) {}

因此,如您所见,那里没有魔力,只有由提供的线程特定变量ThreadLocal

如果您有足够的好奇心,这里是ThreadLocal.get实现(whic返回此线程局部变量的当前线程副本中的值):

/**
 * Returns the value in the current thread's copy of this
 * thread-local variable.  If the variable has no value for the
 * current thread, it is first initialized to the value returned
 * by an invocation of the {@link #initialValue} method.
 *
 * @return the current thread's value of this thread-local
 */
public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null)
            return (T)e.value;
    }
    return setInitialValue();
}

如您所见,它仅依赖于ThreadLocalMap

/**
 * ThreadLocalMap is a customized hash map suitable only for
 * maintaining thread local values. No operations are exported
 * outside of the ThreadLocal class. The class is package private to
 * allow declaration of fields in class Thread.  To help deal with
 * very large and long-lived usages, the hash table entries use
 * WeakReferences for keys. However, since reference queues are not
 * used, stale entries are guaranteed to be removed only when
 * the table starts running out of space.
 */
static class ThreadLocalMap {

getEntry()在地图中执行查找。希望您现在能看到整个图片。

关于潜在的NullPointerException

基本上,只有在作用域处于活动状态时,才可以调用代理的方法,这意味着执行线程应该是servlet请求。因此,使用此方法,所有异步作业,命令等都将失败。

我要说,这是一个很大的难题ScopedProxy。它确实透明地解决了一些问题(例如,简化了呼叫链),但是如果您不遵循规则,则可能会得到java.lang.IllegalStateException: No thread-bound request found

(《Spring
Framework参考文档》
)说:

DispatcherServlet,RequestContextListener和RequestContextFilter都做完全相同的事情,即将HTTP请求对象绑定到为该请求提供服务的Thread。这使得在请求链和会话范围内的Bean可以在调用链的更下游使用。

@Async和请求属性注入

一般来说,没有直接的方法可以解决问题。如前所述,我们具有线程绑定的RequestAttributes。

潜在的解决方案是手动传递所需的对象,并确保将其背后的逻辑@Async考虑在内。

更加明智的解决方案是透明地执行此操作。为了简化阅读,我将复制代码,并将链接放在代码块下。

import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

/**
 * @author Eugene Kuleshov
 */
public abstract class RequestAwareRunnable implements Runnable {
  private final RequestAttributes requestAttributes;
  private Thread thread;

  public RequestAwareRunnable() {
    this.requestAttributes = RequestContextHolder.getRequestAttributes();
    this.thread = Thread.currentThread();
  }

  public void run() {
    try {
      RequestContextHolder.setRequestAttributes(requestAttributes);
      onRun();
    } finally {
      if (Thread.currentThread() != thread) {
        RequestContextHolder.resetRequestAttributes();
      }
      thread = null;
    }
  }

  protected abstract void onRun();
}

这是一个问题:在以下线程中访问作用域代理Bean:

如您所见,此解决方案依赖于事实构造函数将在适当的上下文中执行,因此可以缓存适当的上下文并在以后注入它。

这是挂在会话作用域bean上的另一个非常有趣的主题@Async带注释的方法



 类似资料:
  • 问题内容: 已锁定 。该问题及其答案被锁定,因为该问题是题外话,但具有历史意义。它目前不接受新的答案或互动。 我对这种东西是陌生的,但是最近我已经听到很多关于Node.js有多出色的信息。考虑到我一般喜欢使用jQuery和JavaScript有多少,我不禁想知道如何决定何时使用Node.js。我想到的Web应用程序有点像Bitly-需要一些内容,然后将其存档。 从过去几天我所做的所有作业中,我获得

  • 我是新手,但最近我听到很多关于Node.js有多好的消息。考虑到总体上我是多么热爱使用jQuery和JavaScript,我不禁想知道如何决定何时使用Node.js。我心目中的web应用程序类似于Bitly-获取一些内容,并将其存档。 从过去几天我一直在做的所有作业中,我获得了以下信息。node.js 是一个命令行工具,可以作为常规web服务器运行,允许运行JavaScript程序 使用great

  • 问题内容: CSS如何确定何时将一种样式应用于另一种样式? 我已经遍历了W3CSS3选择器文档几次,这帮助我了解了如何在jQuery中更好地使用CSS选择器,但是并没有真正帮助我理解何时将一个CSS规则应用于另一个CSS规则。 我有以下HTML: 我有以下CSS: 鉴于以上所述,链接1和链接2的样式将由CSS 确定。为什么与Link 2 关联的样式没有优先级? 显然,我可以这样解决: 但是,由于缺

  • 我有一个运行在Tomcat5上的非常好用的web Java1.5web应用程序。应用程序依赖于它的会话,所以只要会话Cookie被传递出去,或者JSESSIONID出现在上下文路径的末尾,就可以正常工作,就像“;JSESSIONID=...” null

  • 问题内容: 只是想了解在AngularJS中使用ngView和ngInclude的方法的确切区别。什么时候在另一个之上使用是正确的?谢谢。 问题答案: ngView与路由配合使用,并且对于角度SPA来说至关重要。它通常用于包含网站的主要内容,即每当用户单击链接时,页眉和页脚之间的位置就会改变。它与路由的集成意味着更改ngView内容也会更改控制器(取决于您的配置)。 ngInclude是通用的包含

  • 本文向大家介绍如何决定使用 HashMap 还是 TreeMap?相关面试题,主要包含被问及如何决定使用 HashMap 还是 TreeMap?时的应答技巧和注意事项,需要的朋友参考一下 对于在 Map 中插入、删除、定位一个元素这类操作,HashMap 是最好的选择,因为相对而言 HashMap 的插入会更快,但如果你要对一个 key 集合进行有序的遍历,那 TreeMap 是更好的选择。