1

我目前正在为我们的 scala 应用程序使用 spring AOP + Ehcache。我真的很喜欢将它与注释一起使用的简单性,但不是使用像 spring 这样的大框架来执行缓存的一部分。

你知道 scala 缓存解决方案而不必使用像 spring 这样的大框架吗?

没有春天的东西:

 @Cacheable(cacheName = "users")
 def getByUserName(userName: String): User = {
   val userEntityFound = dao.findOne(dao.createQuery.field("email").equal(userName))
   userEntityMapper mapToDomainObject userEntityFound
  }
4

1 回答 1

6

我认为您必须区分缓存库和访问它的 API。我见过的在 Scala 环境中使用的缓存库与在 Java 环境中使用的缓存库相同。对于(可能)分布式缓存,使用 Ehcache 或 memcached 之类的东西。对于本地缓存,通常使用 guava 库的缓存实用程序。

为本地缓存 API 编写一个包装器是很容易的,以便有一种更符合 scala 习惯的方式来访问缓存。您在示例中使用的注解是访问 Java 中库抽象的常用方法,但在 Scala 世界中并不常见。表演!例如,框架有一个缓存抽象,默认情况下,它绑定到 Ehcache。允许以下构造:

val user: User = Cache.getOrElseAs[User]("item.key") {
  User.findById(connectedUser)
} 

Twitter 在他们的 scala 实用程序中有一个 guava 缓存的包装器,但删除了它们。我认为是这样,因为在当前的番石榴版本中,直接访问它非常简单/实用。

val cache = 
 CacheBuilder.newBuilder().
  maximumSize(1000).
   build((key:String) => q(key)) 

例如,如果您在范围内有以下隐式转换,这将正常工作:

implicit def functionToCacheLoader[F, T](f: F => T) = {
 new CacheLoader[F, T] {
  def load(key: F) = f(key)
 }
}

最后,向番石榴缓存本身添加一些糖也很容易:

implicit def pimpCache[F, T](cache: Cache[F, T]) = {
 new PimpedCache(cache)
}

class PimpedCache[F, T](cache: Cache[F, T]) {
 def getOption(key: F) = {
  val value = cache.getIfPresent(key)
  if(value == null) None else Some(value)
 }    
}

这些是我使用的缓存的主要抽象。这是一个包含我需要的所有代码的要点的链接。我也有一个播放插件!缓存抽象,它在引擎盖下使用番石榴,如果您需要使用它,我可以分享。

于 2012-09-08T14:47:01.177 回答