SpringCacheに使用可能なCache実装について

# SpringCache
Spring Framework3.1以降追加された機能。
Spring4.1から`JSR-107`のサポートやカスタマイズオプションが増えた。
**「あるメソッドの指定した引数に対する戻り値」** をキャッシュの単位とする。

※指定した引数に対して、メソッドが既に実行されているかどうかをチェックする
→実行されていた場合、実際のメソッドを実行せずにキャッシュを返却する。
→実行されていない場合、そのメソッドを実行し、結果をキャッシュに格納する。

# SpringCacheで用いることが可能なキャッシュ実装
1. JDK(java.util.concurrent.ConcurrentMap)ベース
2. Ehcache2.xベース
3. Gemfireベース
4. Caffeineベース
5. JSR-107ベース
6. Redisベース

※恐らく他にもある
※以下を実装することで拡張可能
- [org.springframework.cache.CacheManager](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/cache/CacheManager.html)
- [org.springframework.cache.Cache](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/cache/Cache.html)

各キャッシュ実装は使用する `CacheManager` を切り替えることによって切り替えが可能。

## 1. ConcurrentHashMapベース
`spring-context-xxx.jar` に格納。
使用する `CacheManager` は `SimpleCacheManager` 。
アプリケーションによって作成されるため、ライフサイクルに拘束される。基本的な使用・テスト・単純アプリに適する。拡張性は優れるが、管理や永続に関する機能は提供されない。

```xml
<!-- simple cache manager -->
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
    <property name="caches">
        <set>
            <bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="books"/>
        </set>
    </property>
</bean>
```

## 2. Ehcache2.xベース
`spring-context-support-xxx.jar` に格納。
使用する `CacheManager` は `EhCacheCacheManager` 。

```xml
<bean id="cacheManager"
        class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcache"/>

<!-- EhCache library setup -->
<bean id="ehcache"
        class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:config-location="ehcache.xml"/>
```

### Ehcacheとは
Javaにおけるキャッシュライブラリのデファクトスタンダード。 `JSR-107(JCache)` の実装ライブラリ。
基本はメモリ上に保存しつつ、ローカルディスクへの退避も可能になっている。
[レプリケーション]やトランザクション機能などを提供する。

使用可能なストレージは以下の通り。

- **Memory Store**  
Javaのヒープメモリ。シリアライズ不可のオブジェクトについても保存可能。
- **off-Heap Store**  
メモリ上に格納するが、GCの対象にはならない。デフォルトでの使用は出来ず、 `Terracotta BigMemory` を使用する必要がある。シリアライズ可能なオブジェクトのみ保存可能。
- **Disk Store**  
ファイルなどのメモリ外ストレージ。シリアライズ可能なオブジェクトのみ保存可能。

### 参考

- [Ehcache 使い方メモ](https://qiita.com/opengl-8080/items/f42664769740674176ff)
- [レプリケーションとは | バックアップとアーカイブ | サービス3選](https://boxil.jp/mag/a2534/#2534-1
- [JCache（Ehcache 3）のメソッドの結果キャッシュを軽く試してみた feat. Guice](https://qiita.com/eiryu/items/9a63e005e4924a43414c)

[レプリケーション]:データレプリケーション。あるデータのコピーを別システム上に作ること。同期したデータはバイナリ単位で完全に一致する。「データのレプリカを作る」という意味が由来。バックアップなどとは異なり、随時更新され、保存媒体も同一のものが用いられる。

## 3. Caffeineベース
`spring-context-support-xxx.jar` に格納。
使用する `CacheManager` は `CaffeineCacheManager` 。
キャッシュはメモリに保持する。Guava+ConcurrentLinkedHashMapのような保持方法。
頻度や最新性に基づいて、最大格納量や最大格納時間を越えた場合にキャッシュリリースを行う機能を提供する。

```xml
<bean id="cacheManager"
        class="org.springframework.cache.caffeine.CaffeineCacheManager"/>
```

### Caffeine Cacheとは
`Google Guava Cache` にインスパイアされてJava8で書き下ろしたキャッシュ機構。
ハイパフォーマンスを謳っている。(Ehcache > Google Guava > Caffeine)
Spring4.3から採用されており、それ以前からサポートされていたGuavaは5.0にて削除された。

### 参考

- [ローカルキャッシュにCaffeineでも](https://kazuhira-r.hatenablog.com/entry/20161204/1480818544)
- [caffeine公式](https://github.com/ben-manes/caffeine)

# 4. Gemfireベース
`CacheManager` はSpring FrameworkではなくSpring Dataにて提供している。

```xml
  <!-- enable declarative caching -->
  <cache:annotation-driven/>

  <gfe:cache id="gemfire-cache"/>

  <!-- declare GemfireCacheManager; must have a bean ID of 'cacheManager' -->
  <bean id="cacheManager" class="org.springframework.data.gemfire.cache.GemfireCacheManager"
      p:cache-ref="gemfire-cache">
```

## GemFireとは
[インメモリデータグリッド]を利用しているため大量なデータへの対応に有利。
VMwareの1製品として作られている。
キーワード：メモリ志向・ディスクバックアップ・弾性スケーラブル・継続利用可能・グローバルレプリケート

[インメモリデータグリッド]:「大量のデータを多数のサーバのメモリで分散して管理する技術」。アプリケーション側からは一つの仮想的なサーバ上にデータがあるものと見られているため、複数サーバの設定をすることはない。トランザクション管理・クエリ検索・データの冗長構成などの機能がある。

## 参考

- [“限界”を突破する技術、「インメモリデータグリッド」 ](http://www.itmedia.co.jp/im/articles/1209/19/news139.html)
- [GemFire 調査メモ](http://exlight.net/devel/sysdev/gemfire.html)
- [Spring Data for Pivotal GemFire Reference Guide](https://docs.spring.io/spring-gemfire/docs/current/reference/html/#bootstrap:cache)

# 5. JSR-107ベース
`spring-context-support-xxx.jar` に格納。
使用する `CacheManager` は `JCacheCacheManager` 。

```xml
<bean id="cacheManager"
        class="org.springframework.cache.jcache.JCacheCacheManager"
        p:cache-manager-ref="jCacheManager"/>

<!-- JSR-107 cache manager setup  -->
<bean id="jCacheManager" .../>
```

# 6. Redisベース
`CacheManager` はSpring FrameworkではなくSpring Dataにて提供している。
使用する `CacheManager` は `RedisCacheManager` 。

## Redisとは
キャッシュ格納先は[インメモリDB]。
一定間隔でスナップショットを撮り、再起動時にメモリに展開してデータの永続性を図る。

[インメモリDB]:対義語は「RDB」「オンディスクDB」。CPUから直接参照できるため、RDBよりも高速。ただし、揮発性のため永続性の担保は難しい。

## 参考

- [Spring Data Redis におけるデフォルト設定の注意点](http://fits.hatenablog.com/entry/2015/08/27/205539)
- [Spring BootでSpring Data Redisを利用する](https://qiita.com/yoshidan/items/f7c10a43d2a40c3ce8df)
- [Redis入門: Redisとは？ インメモリDBについて、memcachedとの違いなど](http://post.simplie.jp/posts/116)
- [Spring BootでRedisにキャッシュする際の抽象化について](https://ishiis.net/2016/09/02/spring-redis-cache/)
- [Redisのインストール・セットアップ](https://qiita.com/KurosawaTsuyoshi/items/f8719bf7c3a10d22a921)

--
## 他参照したリファレンスなど

公式リファレンス

- [8.キャッシュ抽象化(Spring公式リファレンスより)](https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/integration.html#cache)
- [8.5。キャッシュ記憶域の構成](https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/integration.html#cache-store-configuration)

その他

 - [「CGLIBのProxy」使用時にインタフェースに指定したアノテーションが読み取られる](https://qiita.com/kazuki43zoo/items/7f4e97978ae6631ad281#cglib%E3%81%AEproxy%E4%BD%BF%E7%94%A8%E6%99%82%E3%81%AB%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9%E3%81%AB%E6%8C%87%E5%AE%9A%E3%81%97%E3%81%9F%E3%82%A2%E3%83%8E%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%8C%E8%AA%AD%E3%81%BF%E5%8F%96%E3%82%89%E3%82%8C%E3%82%8B-thumbsup)