web-dev-qa-db-ja.com

SpringCache-カスタムCacheManagerを作成します

SpringBootとEhCacheを使用してカレンダーアプリケーションを開発しています。次のメソッドをキャッシュしようとしています:

@Override
@Cacheable(value = "concerts")
public List<Event> getEvents(String eventsForUser, Date startDate, Date endDate) throws Exception {
    return fetchEventsFromTheServer(eventsForUser, startDate, endDate);
}

課題は、返されたキャッシュ結果を操作したいということです。たとえば、特定の日付で別のユーザーのキャッシュがあるかどうかを確認し、代わりにキャッシュを返します(両方のユーザーが特定の基準を満たしている場合)。

したがって、結果を返す前に、次のことを行います。

  • キャッシュされたすべてのエントリのリストを取得するには
  • それらすべてをループして、必要な日付/ユーザーを確認します
  • 適切であると判断された場合-それを返す
  • 見つからない場合-キャッシュが利用できない場合は、メソッドを実行します。

キャッシュされたコンサートですべての操作を行い、他のすべての方法にデフォルトの自動構成されたキャッシュを使用するカスタムキャッシュマネージャーを作成するのが最善だと思いますが、カスタムマネージャーを機能させることができず、何も見つかりませんでしたカスタムCacheManagerを実装する方法の例。

これが私が持っているものです:

Application.Java:

@SpringBootApplication
@ComponentScan
@EnableCaching
@EnableScheduling
public class SpringBootWebApplication extends SpringBootServletInitializer {

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

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(applicationClass);
    }

    private static Class<SpringBootWebApplication> applicationClass = SpringBootWebApplication.class;


    @Bean(name = "eventsCacheManager")
    public EventsCacheManager eventsCacheManager() {

        return new EventsCacheManager();
    }

    @Primary
    @Bean(name = "cacheManager")
    public CacheManager cacheManager() {
        return new EhCacheCacheManager(ehCacheCacheManager().getObject());
    }

    @Bean
    public EhCacheManagerFactoryBean ehCacheCacheManager() {
        EhCacheManagerFactoryBean cmfb = new EhCacheManagerFactoryBean();
        cmfb.setConfigLocation(new ClassPathResource("ehcache.xml"));
        cmfb.setShared(true);
        return cmfb;
    }


}

EventsCacheManager.Java

@Component
public class EventsCacheManager implements CacheManager  {

    @Override
    public Cache getCache(String s) {
        return null;
    }

    @Override
    public Collection<String> getCacheNames() {
        return null;
    }
}

EventsCacheManager.Java-それを実装する方法は?

@Component
public class EventsCacheManager implements CacheManager  {

    @Override
    public Cache getCache(String s) {
        return null;
    }

    @Override
    public Collection<String> getCacheNames() {
        return null;
    }
}

カスタムCacheManagerを実装する方法の例を誰かに教えてもらえれば幸いです。

6
Oleg

私はあなたの要件/ユースケースについて考えることに多くの時間を費やしませんでしたが、「カスタム」CacheManagerロジックが正しいと仮定すると、カスタムCacheManagerがこの状況で機能すると思います。

したがって、デフォルトでは、Springは、「cacheManager」という名前のコンテキストでBeanを検索し、それをすべてのキャッシュ操作に使用します。構成では、2つの「CacheManager」が明確に定義されています...

@Bean(name = "eventsCacheManager")
public EventsCacheManager eventsCacheManager() {

    return new EventsCacheManager();
}

@Primary
@Bean(name = "cacheManager")
public CacheManager cacheManager() {
    return new EhCacheCacheManager(ehCacheCacheManager().getObject());
}

つまり「eventsCacheManager」(カスタム)および「cacheManager」(標準)。実際、「cacheManager」をプライマリとしてマークしました(@Primaryアノテーションを使用)。もちろん、それを行わなかった場合、自動配線を実行するときにコンテキスト内で特定のタイプ(つまり、CacheManager)の複数のBeanが見つかったため、Springは確かに不平を言っていたでしょう(デフォルトでは、タイプごとに自動配線されます)。

したがって、特定のサービス呼び出しで実行時に使用するキャッシュ管理戦略(つまり、CacheManager)を呼び出すには、SpringにどのCacheManager(別名戦略)を指定する必要もあります。使用、そのように...

@Override
@Cacheable(value = "concerts", cacheManager="eventsCacheManager")
public List<Event> getEvents(String eventsForUser, Date startDate, Date endDate) throws Exception {
    return fetchEventsFromTheServer(eventsForUser, startDate, endDate);
}

つまり@CacheableアノテーションのcacheManager属性を使用して、使用するキャッシュ戦略を示します。

詳細については、Springのリファレンスドキュメント カスタムキャッシュ解像度 を参照してください。

これがあなたを動かすのに役立つことを願っています。

2
John Blum

あなたの質問に対する私の理解から、あなたは問題を間違った方法で見ていると思います。

派生情報を抽出するためにキャッシュの内容を参照する代わりに、メインデータのロード時に派生情報をキャッシュに挿入する必要があります。

たとえば、月ベースの情報をロードする場合は、すぐに日ベースの情報に分割し、それもキャッシュに入れます。

この説明は、カスタムキャッシュロードロジックが必要なため、実行したいことがSpringキャッシング抽象化の機能を超えていることも明確に示しているはずです。

したがって、CacheManagerをハッキングしてそのロジックを非表示にすることはお勧めしませんが、代わりにデータ読み込みロジックからハッキングします。

1
Louis Jacomet