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

当我读到scalatra的源码时,发现有一些代码是这样的:

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

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

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

(我是新来的Scala,如果你可以提供一些代码,这将是伟大的)

DynamicVariable是贷款和dynamic范围模式的实现。 DynamicVariable用例与Java中的ThreadLocal非常相似(事实上, DynamicVariable在后台使用InheritableThreadLocal ) – 当需要在封闭范围内进行计算时,每个线程都有自己的副本的variables的值:

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

鉴于DynamicVariable使用可inheritance的ThreadLocal ,variables的值被传递给上下文中产生的线程:

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

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

使HttpServletResponseHttpServletRequestdynamicvariables(并因此绑定到处理请求的特定线程)只是在代码中任何地方获取它们的最简单方法(不通过方法参数或其他任何明确的方式)。

Vasil很好地回答了这个问题,但是我会添加一个简单的例子来进一步帮助理解。

假设我们必须使用一些使用println()来遍历stdout的代码。 我们希望这个输出到一个日志文件,但我们没有访问源。

  • println()使用Console.println()
  • Console.println() (幸运的是) 基于 DynamicVariable[PrintStream] ,默认为java.lang.System.out
  • Console定义withOut只是转发给dynamicvariables的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 

这是一个最小的片段:

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

输出将是:

 withoutValue withValue withoutValue