Когда мы должны использовать scala.util.DynamicVariable?
Когда я прочитал исходники скалатры, я обнаружил, что есть такой код:
protected val _response = new DynamicVariable[HttpServletResponse](null)
protected val _request = new DynamicVariable[HttpServletRequest](null)
Есть интересный класс с именем DynamicVariable
, Я посмотрел на документ этого класса, но я не знаю, когда и почему мы должны его использовать? Оно имеет withValue()
который обычно используется.
Если мы не используем его, то какой код мы должны использовать вместо этого, чтобы решить проблему, которую он решил?
(Я новичок в Scala, если вы можете предоставить некоторый код, это будет здорово)
3 ответа
DynamicVariable
это реализация кредита и динамические шаблоны объема. Вариант использования DynamicVariable
очень похоже на ThreadLocal
в Java (на самом деле, 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
}
}
DynamicVariable
(а также ThreadLocal
) используется в Scalatra по той же причине, что и во многих других инфраструктурах (Lift, Spring, Struts и т. д.) - это ненавязчивый способ хранения и передачи информации, специфичной для контекста (потока).
Изготовление HttpServletResponse
а также HttpServletRequest
Динамические переменные (и, таким образом, привязка к определенному потоку, который обрабатывает запрос) - это просто самый простой способ получить их где-нибудь в коде (не передавая аргументы метода или в противном случае явно).
Василь хорошо ответил на этот вопрос, но я добавлю еще один простой пример, который может помочь понять.
Предположим, мы должны использовать некоторый код, который использует println() для записи во всем stdout. Мы хотим, чтобы этот вывод шел в файл журнала, но у нас нет доступа к источнику.
println()
использованияConsole.println()
Console.println()
(к счастью) основан на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
Это минимальный фрагмент:
val dyn = new DynamicVariable[String]("withoutValue")
def print=println(dyn.value)
print
dyn.withValue("withValue") {
print
}
print
Выход будет:
withoutValue
withValue
withoutValue