在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