栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

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

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

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

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

春天有RequestContextHolder

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

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

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

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

    public static void setRequestAttributes(RequestAttributes attributes, boolean inheritable) {}

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

ThreadLocal

如果您有足够的好奇心,这里是

ThreadLocal.get
实现(whic返回此线程局部变量的当前线程副本中的值):

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

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;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带注释的方法



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/369686.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号