2011-02-25 164 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 
相關問題