Spring BootでCacheableが効かなかった

はじめに

エキサイト株式会社 バックエンドエンジニアの山縣です。

エキサイトホールディングス Advent Calendar 2021の9日目の記事です。 qiita.com

タイトルのとおりですが、Spring BootでCacheableが効かなかったことがありました。 これについて調査したことと、原因について紹介します。

調査

下記に簡単なメソッドを用意しました。 getItem1メソッドはItemServiceにあるgetItemから呼ばれています。 このときに、下記サービスを呼び出してItemをキャッシュすることを試みます。

// インタフェース
public interface ItemService {
    Item getItem(String name);
}

// 実装
@Service
@RequiredArgsConstructor
public class ItemServiceImpl implements ItemService {
    @Override
    public Item getItem(String name) {
        return this.getItem1(name);
    }

    @Cacheable(cacheNames = "item", key = "#name")
    public Item getItem1(String name) {
        return new Item("1", "item1");
    }
}

結果

getItem1メソッドに@Cacheableを付与したときに、Itemがキャッシュされないことを確認しました。 getItem1メソッドから、getItemメソッドにアノテーションを移動するとキャッシュされます。

原因

これは、Cacheableそのものの問題ではないことがわかりました。 CacheableはSpring AOPを採用した実装であるため、ItemServiceImplの中で自身のメソッド呼びだしていることがキャッシュが効かないことの原因でした。 インタフェースを実装したメソッドに対して素直に@Cacheableを付与したほうがよさそうです。

おわりに

本記事では、Cacheableがうまく動かなかったときの原因について紹介しました。 実行時にエラーが出ずになかなか解決できなかったので、かなり詰まってしまいました。 最後まで読んでいただき、ありがとうございました!