我们什么时候应该使用 scala.util.DynamicVariable?

发布于 2024-10-18 23:24:40 字数 404 浏览 5 评论 0 原文

当我阅读scalatra的源代码时,我发现有一些代码,例如:

protected val _response   = new DynamicVariable[HttpServletResponse](null)
protected val _request    = new DynamicVariable[HttpServletRequest](null)

有一个有趣的类,名为DynamicVariable。我看过这个类的文档,但我不知道什么时候以及为什么我们应该使用它?它有一个通常使用的withValue()

如果我们不使用它,那么我们应该使用什么代码来解决它解决的问题?

(我是scala新手,如果你能提供一些代码,那就太好了)

When I read the source of scalatra, I found there are some code like:

protected val _response   = new DynamicVariable[HttpServletResponse](null)
protected val _request    = new DynamicVariable[HttpServletRequest](null)

There is an interesting class named DynamicVariable. I've looked at the doc of this class, but I don't know when and why we should use it? It has a withValue() which is usually be used.

If we don't use it, then what code we should use instead, to solve the problem it solved?

(I'm new to scala, if you can provide some code, that will be great)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

被你宠の有点坏 2024-10-25 23:24:40

DynamicVariable 是贷款和动态范围模式的实现。 DynamicVariable 的用例与 Java 中的 ThreadLocal 非常相似(事实上,DynamicVariable 使用 InheritableThreadLocal > 在幕后) - 当您需要在封闭范围内进行计算时使用它,其中每个线程都有自己的变量值副本:

dynamicVariable.withValue(value){ valueInContext =>
  // value used in the context
} 

假设 DynamicVariable 使用可继承的 ThreadLocal ,变量的值被传递给上下文中生成的线程:

dynamicVariable.withValue(value){ valueInContext =>
  spawn{
    // value is passed to the spawned thread
  }
}

DynamicVariable(和 ThreadLocal)在 Scalatra 中使用,其原因与在许多应用程序中使用的原因相同其他框架(Lift、Spring、Struts 等)- 这是一种存储和传递上下文(线程)特定信息的非侵入式方式。

制作 HttpServletResponseHttpServletRequest 动态变量(因此绑定到处理请求的特定线程)只是在代码中的任何位置获取它们的最简单方法(而不是通过方法参数或其他明确的方式)。

DynamicVariable is an implementation of the loan and dynamic scope patterns. Use-case of DynamicVariable is pretty much similar to ThreadLocal in Java (as a matter of fact, DynamicVariable uses InheritableThreadLocal behind the scenes) - it's used, when you need to do a computation within an enclosed scope, where every thread has it's own copy of the variable's value:

dynamicVariable.withValue(value){ valueInContext =>
  // value used in the context
} 

Given that DynamicVariable uses an inheritable ThreadLocal, value of the variable is passed to the threads spawned in the context:

dynamicVariable.withValue(value){ valueInContext =>
  spawn{
    // value is passed to the spawned thread
  }
}

DynamicVariable (and ThreadLocal) is used in Scalatra for the same reason it's used in many other frameworks (Lift, Spring, Struts, etc.) - it's a non-intrusive way to store and pass around context(thread)-specific information.

Making HttpServletResponse and HttpServletRequest dynamic variables (and, thus, binding to a specific thread that processes request) is just the easiest way to obtain them anywhere in the code (not passing through method arguments or anyhow else explicitly).

一场春暖 2024-10-25 23:24:40

Vasil 很好地回答了这个问题,但我将添加一个额外的简单示例,可能会进一步帮助理解。

假设我们必须使用一些使用 println() 的代码来写入所有 stdout。我们希望将此输出发送到日志文件,但我们无权访问源代码。

  • println() 使用 Console.println()
  • Console.println() (幸运的是)是 基于默认的DynamicVariable[PrintStream] java.lang.System.out
  • Console 定义 withOut 只转发到动态变量的 withValue

我们可以用它来简单地修复我们的问题问题:

def noisy() { println("robot human robot human") }
noisy() // prints to stdout
val ps = new java.io.PrintStream("/tmp/mylog")
scala.Console.withOut(ps) { noisy() } // output now goes to /tmp/mylog file

This is well answered by Vasil, but I'll add an additional simple example that might further help understanding.

Suppose we must use some code that uses println() to write all over stdout. We want this output to go to a log file, but we don't have access to the source.

  • println() uses Console.println()
  • Console.println() (fortunately) is based on a DynamicVariable[PrintStream] that defaults to java.lang.System.out
  • Console defines withOut that just forwards to the dynamic variable's withValue

We can use this to simply fix our issue:

def noisy() { println("robot human robot human") }
noisy() // prints to stdout
val ps = new java.io.PrintStream("/tmp/mylog")
scala.Console.withOut(ps) { noisy() } // output now goes to /tmp/mylog file
ヤ经典坏疍 2024-10-25 23:24:40

这是一个最小的片段:

val dyn = new DynamicVariable[String]("withoutValue")
def print=println(dyn.value)
print
dyn.withValue("withValue") {
  print
}
print

输出将是:

withoutValue
withValue
withoutValue

This is a minimal snippet:

val dyn = new DynamicVariable[String]("withoutValue")
def print=println(dyn.value)
print
dyn.withValue("withValue") {
  print
}
print

The output will be:

withoutValue
withValue
withoutValue
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文