Scala: Ergebnisse der Ausführung der Caching-Methode

    Manchmal ist es notwendig, die Ergebnisse der Methodenausführung zwischenzuspeichern. Eine der möglichen Lösungen für Java wird hier beschrieben . Alles ist im Prinzip trivial: EHCache, Spring AOP zum Abfangen von Anrufen, ein bisschen Code.

    Überlegen Sie sich, wie mir scheint, eine elegantere Lösung für Scala.

    Wir formulieren das Problem genauer. Sie müssen ein Mixin erstellen. Wenn Sie es der Service-Implementierung hinzufügen, können Sie die Ergebnisse der Methodenausführung wie folgt zwischenspeichern: Beginnen wir mit einem einfachen DSL, um die Cache-Parameter zu bestimmen. Wir benötigen eine Klasse zur Beschreibung der Caching-Optionen, die Folgendes enthält:

        final val CACHE_FIRST_USER_CREATED = "firstUserCreated"

        def isFirstUserCreated:Boolean = cache (

          {userDAO.getCount>0} withKey CACHE_FIRST_USER_CREATED forever

        )




    • Schlüssel
    • Lebensdauer der Aufnahme
    • Tatsächlich berechnet die Funktion den Rückgabewert.

      class CacheOptions[T](fn: =>T) {

        var time = -1

        var key:String = "key"

      }


    Wir definieren die forever, expirationTime, withKey-Methoden, die Standardkonvertierung für Funktionen zum Auffüllen von Objekten dieser Klasse und die _execFn-Methode, mit der der als Name übergebene fn-Wert berechnet wird. Ein Ausdruck des Formulars: Gibt ein CacheOptions [String] -Objekt mit ausgefüllten Feldern für Zeit, Schlüssel und FN zurück. Lass uns direkt zum Cachen gehen. Der eingangs erwähnte Artikel verwendet EHCache, um die Ergebnisse zwischenzuspeichern. Nichts hindert Sie daran, dasselbe zu tun. Der Einfachheit halber zeige ich die Cachergebnisse jedoch in einer einfachen ConcurrentHashMap. Eigentlich also die Cache-Methode selbst: Keine Speichertechnologie - ein Versuch, aus dem Cache auszuwählen, den Zeitstempel des Datensatzes zu überprüfen, ihn auszuführen und, falls erforderlich, zu zwischenspeichern.

      class CacheOptions[T](fn: =>T) {

        var time = -1

        var key:String = "key"

        def _execFn:T = fn

        def forever = {this.time= -1;this}

        def expirationTime(time:Int) = {this.time=time;this}

        def withKey(key:String) = {this.key=key;this}

      }



      implicit def fn2co[T](fn: =>T) = new CacheOptions[T](fn)





    { "lazy value" } withKey "mykey" expirationTime 30000







      private val cache = new ConcurrentHashMap[String,CacheRecord]



      def cache[T](co:CacheOptions[T]):T = {

        val timestamp = System.currentTimeMillis()

        val cr = cache.get(co.key)

        (cr==null) match {

          case true => refresh(timestamp,co)

          case false => 

            if (co.time>0 && (timestamp-cr.timestamp)>co.time)

              refresh(timestamp,co)

            else

              cr.obj.asInstanceOf[T]

        }

      }



      private def refresh[T](timestamp:Long, co:CacheOptions[T]):T = {

        val cr = new CacheRecord(timestamp, co._execFn.asInstanceOf[AnyRef])

        cache.put(co.key, cr)

        cr.obj.asInstanceOf[T]

      }






    Fügen Sie eine einfache Methode hinzu, um das Ausschließen von Einträgen aus dem Cache zu erzwingen: Fertig! Minus, im Vergleich zur Verwendung von spring aop - es ist notwendig, den Vorgang der Schlüsselerstellung in Abhängigkeit von den Eingabeparametern zu beschreiben (bei der Entscheidung über spring aop geschieht dies automatisch). Pluspunkte - Einfachheit, die Fähigkeit, das Löschen von Datensätzen zu erzwingen.
      def evict(key:String):Unit = cache.remove(key)






    Als Beispiel habe ich Caching in ConcurrentHashMap gezeigt. Die Nachteile dieser Lösung im Vergleich zur Verwendung von EHCache liegen auf der Hand. Es gibt keine Möglichkeit, die Anzahl der Einträge im Cache zu begrenzen und eine Strategie zum Löschen von Einträgen festzulegen. Sie müssen sicherstellen, dass die zurückgegebenen Werte unveränderlich sind. Andernfalls besteht die Möglichkeit, die Werte zu ändern befindet sich im Cache. All diese Probleme können jedoch vermieden werden, indem dieses Merkmal auf die Verwendung von EHCache oder einer anderen Bibliothek "umgeschaltet" wird. Dies ist eine Frage von 5 Minuten.

    Jetzt auch beliebt: