Lift当中的AnyVarTrati源码解析

时间:2023-01-08 19:37:39

在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