当我阅读scalatra的来源时,我发现有一些代码如:
protected val _response = new DynamicVariable[HttpServletResponse](null)
protected val _request = new DynamicVariable[HttpServletRequest](null)
有一个名为DynamicVariable
的有趣类。我看过这堂课的文件,但我不知道何时以及为什么要使用它?它通常使用withValue()
。
如果我们不使用它,那么我们应该使用什么代码来解决它解决的问题?
(我是scala的新手,如果你能提供一些代码,那就太棒了)
答案 0 :(得分:56)
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
}
}
Scalatra中使用了 DynamicVariable
(和ThreadLocal
),原因与它在许多其他框架(Lift,Spring,Struts等)中使用的原因相同 - 它是一种非侵入式的存储和存储方式传递上下文(线程) - 特定信息。
使HttpServletResponse
和HttpServletRequest
动态变量(以及绑定到处理请求的特定线程)只是在代码中的任何位置获取它们的最简单方法(不通过方法参数或无论如何明确地)。
答案 1 :(得分:24)
Vasil已经很好地回答了这个问题,但我会添加一个可能进一步帮助理解的简单例子。
假设我们必须使用一些使用println()来编写遍历stdout的代码。我们希望此输出转到日志文件,但我们无法访问源。
println()
使用Console.println()
Console.println()
(幸运的是)based on一个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
答案 2 :(得分:17)
这是一个最小的片段:
val dyn = new DynamicVariable[String]("withoutValue")
def print=println(dyn.value)
print
dyn.withValue("withValue") {
print
}
print
输出将是:
withoutValue
withValue
withoutValue