什么时候应该使用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等)中使用的原因相同 – 这是存储和传递上下文(线程)特定信息的非侵入性方式。
使HttpServletResponse
和HttpServletRequest
dynamicvariables(并因此绑定到处理请求的特定线程)只是在代码中任何地方获取它们的最简单方法(不通过方法参数或其他任何明确的方式)。
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