2011-02-25 128 views
42

当我读到了Scalatra的来源,我发现有像一些代码:什么时候应该使用scala.util.DynamicVariable?

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

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

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

(我是新来斯卡拉,如果你能提供一些代码,那将是巨大的)

+0

HTTP://scala-programming-language.1934581.n4.nabble。COM /斯卡拉线程本地上下文制造,易于使用 - 斯卡拉 - td1997909.html – 2011-02-25 12:22:38

回答

50

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

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

DynamicVariable(和ThreadLocal)为:

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

鉴于DynamicVariable使用一个可继承ThreadLocal,该变量的值被传递给线程在上下文在产生在Scalatra中使用它的原因与许多其他框架(Lift,Spring,Struts等)中使用的原因相同 - 这是一种非侵入性的方式来存储和传递上下文(线程)特定的信息。

制作HttpServletResponseHttpServletRequest动态变量(和,因此,结合到处理请求的特定线程)只是在代码的任何地方获得他们(未通过方法的参数或其他无论如何明确),最简单的方法。

22

这很好的回答了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 
13

这是一个最小的片段:

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

的输出将是:

withoutValue 
withValue 
withoutValue 
相关问题