LoginSignup
3
4

More than 5 years have passed since last update.

JCache(Ehcache 3)のメソッドの結果キャッシュを軽く試してみた feat. Guice

Last updated at Posted at 2016-12-24

使ったもの

  • JCache API 1.0.0
  • Ehcache 3
  • Guice
// Groovy Version: 2.4.5 JVM: 1.8.0_77 Vendor: Oracle Corporation OS: Mac OS X
@Grab('javax.cache:cache-api:1.0.0')
@Grab('org.ehcache:ehcache:3.2.0')
@Grab('org.jsr107.ri:cache-annotations-ri-guice:1.0.0')
@Grab('com.google.inject:guice:4.1.0')

import com.google.inject.AbstractModule
import com.google.inject.Guice
import com.google.inject.Injector
import org.jsr107.ri.annotations.guice.module.CacheAnnotationsModule

import javax.cache.CacheManager
import javax.cache.Caching
import javax.cache.annotation.CacheDefaults
import javax.cache.annotation.CacheResult
import javax.cache.configuration.Configuration
import javax.cache.configuration.MutableConfiguration
import javax.cache.expiry.AccessedExpiryPolicy
import javax.cache.expiry.Duration
import javax.cache.spi.CachingProvider
import java.text.SimpleDateFormat
import java.util.concurrent.TimeUnit

@CacheDefaults(cacheName = 'simpleCache')
class Sample {
    @CacheResult
    String hello() {
        new SimpleDateFormat('yyyy-MM-dd HH:mm:ss.SSS').format(new Date())
    }
}

CachingProvider cachingProvider = Caching.getCachingProvider();
CacheManager cacheManager = cachingProvider.getCacheManager();

Configuration<Object, Object> config =
        new MutableConfiguration<Object, Object>()
                .setTypes(Object.class, Object.class)
                // キャッシュの有効期間は1秒
                .setExpiryPolicyFactory(AccessedExpiryPolicy.factoryOf(new Duration(TimeUnit.SECONDS, 1)));

cacheManager.createCache('simpleCache', config)

Injector injector = Guice.createInjector(new CacheAnnotationsModule())

Sample sample = injector.getInstance(Sample.class);
println sample.hello()
println sample.hello()
println sample.hello()
println sample.hello()
println sample.hello()
// ↑は全て同じ時刻が出力されること
TimeUnit.SECONDS.sleep(1)
// キャッシュ切れで取得し直して上とは違う時刻が出力されること
println sample.hello()

結果

2016-12-24 14:04:27.284
2016-12-24 14:04:27.284
2016-12-24 14:04:27.284
2016-12-24 14:04:27.284
2016-12-24 14:04:27.284
2016-12-24 14:04:28.312 # 結果がここだけ上と違う。想定通り

CDIとかを使わないでメソッドの結果をキャッシュするのをサクッと試そうとしただけなのに、20時間ほど要してしまった。。

最初の想定としては、

  1. JCache APIと実装を依存性に追加
  2. POJOのキャッシュしたいメソッドに @javax.cache.annotation.CacheResult 付ける

くらいで出来るだろうと思っていたが、全然違った。

実際は、

  1. JCache APIと実装を依存性に追加
  2. CDIやSpring Framework以外で使うためにはGuiceしか選択肢がなさそうなのでGuiceを依存性に追加
  3. Guice用のcache-annotations-riを依存性に追加
  4. POJOのキャッシュしたいメソッドに @javax.cache.annotation.CacheResult 付ける
  5. javax.cache.annotation.CacheResolverFactoryやJCacheのInterceptorの設定をする

というように、かなり込み入ったことが必要だった。

よもやま

keyとvalueを共にjava.lang.Objectで利用しているが、これはorg.jsr107.ri.annotations.DefaultCacheResolverFactory#getCacheResolverjavax.cache.CacheManager#getCache(java.lang.String)を中で呼んでいてEhcacheの実装を見たところ、key, valueがObjectになっていないとダメなことが分かったため。

javax.cache.CacheManager#getCache(java.lang.String, java.lang.Class<K>, java.lang.Class<V>)を呼ぶようにすれば、任意の型で扱えるはずなので、CacheResolverFactoryを自分で実装すれば変えられそう。とりあえず今回はさっさと動かすことを重視してkey, valueをObjectにした。

Interceptorの設定は完全にFathomというフレームワークのコードを利用している。ありがたや。。今度このフレームワーク自体も試してみたい。

[追記] ↑ @kazuhira_r さんのご指摘により、org.jsr107.ri.annotations.guice.module.CacheAnnotationsModuleを使うようにしてコード量削減。

所感

JCacheはBean Validationのように雰囲気とノリと勢いで試せるものではなかった。ドキュメントのサンプルもイマイチ役に立たなかったし。

参考

3
4
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4