Lift当中的AnyVarTrati源码解析
在Lift2.0当中,AnyVarTrait是一个非常重要的trait,很多重要的像RequestVar,SessionVar都是继续该接口的,
首先看下大致接口代码
abstract class AnyVar[T, MyType <: AnyVar[T, MyType]](dflt: => T) extends AnyVarTrait[T, MyType] {
self: MyType =>
protected def calcDefaultValue: T = dflt
}
/**
* Abstract a request or a session scoped variable.
*/
trait AnyVarTrait[T, MyType <: AnyVarTrait[T, MyType]] extends PSettableValueHolder[T] with HasCalcDefaultValue[T] {
AnyVarTrait继承了PSettableValueHolder,它的接口是:
trait ValueHolder {
type ValueType
def is: ValueType
def get: ValueType
}
trait SettableValueHolder extends ValueHolder {
def set(in: ValueType): ValueType
}
trait PValueHolder[T] extends ValueHolder {
type ValueType = T
// def manifest: Manifest[T]
}
trait PSettableValueHolder[T] extends PValueHolder[T] with SettableValueHolder
}
}
PSettableValueHolder主要是实现了类似于get,set的这样的方法,比较简单,写一个比较简单的实现PSettableValueHolder的例子:
class Example
trait ValueHolder{
type ValueType
def is: ValueType
def get: ValueType
}
trait SettableValueHolder extends ValueHolder{
def set(in: ValueType): ValueType
}
trait PValueHolder[T] extends ValueHolder{
type ValueType = T
}
trait PSettableValueHolder[T] extends PValueHolder[T] with SettableValueHolder
class TestPSettableValueHolder[T] extends PSettableValueHolder[T]
{
protected var testVal: T=_
def set(in: T):T ={
testVal=in
in
}
def get:T={
testVal
}
def is:T={
testVal
}
}
object Test{
def main(args: Array[String]){
val test=new TestPSettableValueHolder[String]
test.set("Test22")
println(test.get)
}
}
需要重载的方法:
protected lazy val name = VarConstants.varPrefix+getClass.getName+"_"+__nameSalt protected def findFunc(name: String): Box[T] protected def setFunc(name: String, value: T): Unit protected def clearFunc(name: String): Unit protected def wasInitialized(name: String): Boolean protected def calcDefaultValue: T /** * A non-side-effecting test if the value was initialized */ protected def testWasSet(name: String): Boolean protected def __nameSalt = "" type CleanUpParam /** * Different Vars require different mechanisms for synchronization. This method implements * the Var specific synchronization mechanism */ def doSync[F](f: => F): F
实现了PSettableValueHolder[T] trait的方法:
/**
* The current value of the variable
*/
def is: T = doSync {
findFunc(name) match {
case Full(v) => v
case _ => val ret = calcDefaultValue
testInitialized
apply(ret)
// Use findFunc so that we clear the "unread" flag
findFunc(name) match {
case Full(v) => v
case _ => ret
}
}
}
private def testInitialized: Unit = doSync {
if (!wasInitialized(name)) {
registerCleanupFunc(_onShutdown _)
}
}
/**
* Shadow of the 'is' method
*/
def get: T = is
/**
* Shadow of the apply method
*/
def set(what: T): T = apply(what)
该trait的apply实现:
/**
* Set the session variable
*
* @param what -- the value to set the session variable to
*/
def apply(what: T): T = {
testInitialized
setFunc(name, what)
what
}
最后一个该trait非常重要的方法 :在该var的生命周期内去修改它的Value:
/**
* Change the value of the Var for the lifespan of the function
*/
def doWith[F](newVal: T)(f: => F): F = {
val old = findFunc(name)
setFunc(name, newVal)
try {
f
} finally {
old match {
case Full(t) => setFunc(name, t)
case _ => clearFunc(name)
}
}
}
再来看下该trait的具体实现:SessionVar和RequestVar
SessionVar,看下他的几个主要实现AnyVarTrait的实现:
override protected def findFunc(name: String): Box[T] = S.session match {
case Full(s) => s.get(name)
case _ =>
if (showWarningWhenAccessedOutOfSessionScope_?)
logger.warn("Getting a SessionVar "+name+" outside session scope") // added warning per issue 188
Empty
}
override protected def setFunc(name: String, value: T): Unit = S.session match {
case Full(s) => s.set(name, value)
case _ =>
if (showWarningWhenAccessedOutOfSessionScope_?)
logger.warn("Setting a SessionVar "+name+" to "+value+" outside session scope") // added warning per issue 188
}
/**
* Different Vars require different mechanisms for synchronization. This method implements
* the Var specific synchronization mechanism
*/
def doSync[F](f: => F): F = S.session match {
case Full(s) =>
// lock the session while the Var-specific lock object is found/created
val lockName = name + VarConstants.lockSuffix
val lockObj = s.synchronized {
s.get[AnyRef](lockName) match {
case Full(lock) => lock
case _ => val lock = new AnyRef
s.set(lockName, lock)
lock
}
}
// execute the query in the scope of the lock obj
lockObj.synchronized {
f
}
case _ => f
}
RequestVar的实现:
override protected def findFunc(name: String): Box[T] = RequestVarHandler.get(name)
override protected def setFunc(name: String, value: T): Unit = RequestVarHandler.set(name, this, value)
override protected def clearFunc(name: String): Unit = RequestVarHandler.clear(name)
override protected def wasInitialized(name: String): Boolean = {
val bn = name + VarConstants.initedSuffix
val old: Boolean = RequestVarHandler.get(bn) openOr false
RequestVarHandler.set(bn, this, true)
old
}
/**
* Different Vars require different mechanisms for synchronization. This method implements
* the Var specific synchronization mechanism
*/
def doSync[F](f: => F): F = f // no sync necessary for RequestVars... always on the same thread
浙公网安备 33010602011771号