SpringBootでEhCashe2.xでキャッシュを使う


背景

Spring Bootを利用していて、キャッシュを実装したくなったので試しました。

実行環境

  • Spring Boot v2.2.4.RELEASE

Spring Bootでのキャッシュ

Spring Bootではいくつかのキャッシュが利用できます。
https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/boot-features-caching.html

うち、上から眺めていってEhCache2.xは導入が簡単そうに見えます。
クラスパスにehcache.xml があれば利用されるとのことなので、導入が簡単そうに見えるので、試してみます。

EhCache 2.x

実装

キャッシュを利用するメソッドの呼び出し元

今回は@SpringBootApplication のアノテーションをつけたクラスから呼び出してみます。
@EnableCaching のアノテーションをつけます

CacheApplication.java
@SpringBootApplication
@EnableCaching
public class CacheApplication implements CommandLineRunner {

    @Autowired
    Cache cache;

    private final static Logger logger = LoggerFactory.getLogger(CacheApplication.class);
    private final static DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");

    public static void main(String[] args) {
        SpringApplication.run(CacheApplication.class, args);
    }

    public void run(String[] args){

        this.getValue("キャッシュされる");
        this.getValue("キャッシュされる");//キャッシュされる
        this.getValue("引数が違うのでキャッシュされない");//引数が違うのでキャッシュされない
        this.getValue("キャッシュされる");//引数違うのを挟んでキャッシュされる
        try {
            Thread.sleep(3000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.getValue("キャッシュされる");//引数が同じだけど生存時間を過ぎているのでキャッシュされない
    }

    public void getValue(String key){
        logger.info(key + " Start at: " + LocalDateTime.now().format(dateTimeFormatter));
        String ret = cache.getFromCache(key); //キャッシュが有効なメソッド
        logger.info(ret + " End at: " + LocalDateTime.now().format(dateTimeFormatter));
    }
}

キャッシュを利用するクラス

キャッシュを有効にしたいメソッドに@Cacheableをつけます

Cache.java
@Component
public class Cache {

    @Cacheable("getCache") //このメソッドについてキャッシュを有効にする
    public String getFromCache(String key){
        try {
            Thread.sleep(3000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "End getFromCache:" + key;
    }
}

pom.xml

pom.xmlにspring-boot-starter-cacheehcacheの2系を追加します。

pom.xml
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
  <groupId>net.sf.ehcache</groupId>
  <artifactId>ehcache</artifactId>
  <version>2.10.3</version>
</dependency>

ehcache.xml

ehcache.xmlをsrc/main/resources/ 以下に作成します。
timeToLiveSecondsを5として、キャッシュの生存時間は5秒の設定にしておきます。

ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <diskStore path="java.io.tmpdir"/>
    <cache
            name="getCache"
            timeToLiveSeconds="5"
            maxEntriesLocalHeap="0">
    </cache>
</ehcache>

application.properties

application.propertiesには、ehcacheを利用するよう以下の設定を追加します。
利用できるキャッシュがehcacheのみならばここは不要です。

spring.cache.type=ehcache

実行

実行します。
実行結果はこうなりました。

2020-02-29 21:29:48 - キャッシュされる Start at: 21:29:48
2020-02-29 21:29:51 - End getFromCache:キャッシュされる End at: 21:29:51
2020-02-29 21:29:51 - キャッシュされる Start at: 21:29:51
2020-02-29 21:29:51 - End getFromCache:キャッシュされる End at: 21:29:51
2020-02-29 21:29:51 - 引数が違うのでキャッシュされない Start at: 21:29:51
2020-02-29 21:29:54 - End getFromCache:引数が違うのでキャッシュされない End at: 21:29:54
2020-02-29 21:29:54 - キャッシュされる Start at: 21:29:54
2020-02-29 21:29:54 - End getFromCache:キャッシュされる End at: 21:29:54
2020-02-29 21:29:57 - キャッシュされる Start at: 21:29:57
2020-02-29 21:30:00 - End getFromCache:キャッシュされる End at: 21:30:00

以下で結果を見ていきます。
一回目は3秒かかっているのに対し、二回目は一瞬なのでキャッシュが効いているようです。

2020-02-29 21:29:48 - キャッシュされる Start at: 21:29:48
2020-02-29 21:29:51 - End getFromCache:キャッシュされる End at: 21:29:51
2020-02-29 21:29:51 - キャッシュされる Start at: 21:29:51
2020-02-29 21:29:51 - End getFromCache:キャッシュされる End at: 21:29:51

違う引数を渡した際はキャッシュされないので、また3秒かかっています。

2020-02-29 21:29:51 - 引数が違うのでキャッシュされない Start at: 21:29:51
2020-02-29 21:29:54 - End getFromCache:引数が違うのでキャッシュされない End at: 21:29:54

以下については生存時間の5秒を過ぎているので、キャッシュがされず、3秒かかっています。

2020-02-29 21:29:57 - キャッシュされる Start at: 21:29:57
2020-02-29 21:30:00 - End getFromCache:キャッシュされる End at: 21:30:00

意図通りのキャッシュの挙動となりました。

所感

SpringBootとEhCache2.Xは、アノテーションと設定ファイルだけでキャッシュが実装できるので手っ取り早いと思いました。
ただ、EhCache3系がすでに利用できるのをその後知りまして、あえてEhCache2系を使うことはあまりないかもしれません。

caffeineを試したら同じようにキャッシュが実装できたのでそちらも使えそうです。
以下記事が参考になりました。
https://qiita.com/yut_arrows/items/4b664acdfa852c0bd6cd