Spring Cache - 创建自定义CacheManager

时间:2016-06-13 07:52:35

标签: java spring-boot ehcache spring-cache

我正在使用Spring Boot和EhCache开发日历应用程序。 我正在尝试缓存以下方法:

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

挑战是我想操纵返回的缓存结果。例如,检查是否存在给定日期的缓存,但是对于不同的用户,然后返回它(只要两个用户都满足特定条件)。

所以,在返回结果之前我想:

  • 获取所有缓存条目的列表
  • 遍历所有这些并检查所需的日期/用户
  • 如果发现合适 - 返回
  • 如果找不到 - 缓存不可用,请运行该方法。

我认为最好的方法是创建一个自定义缓存管理器,它将使用缓存的Concert进行所有操作,并为所有其他方法使用默认的自动配置缓存,但我无法让我的自定义管理器工作而不是找到关于如何实现自定义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

,我真的很感激。

2 个答案:

答案 0 :(得分:2)

我没有花太多时间考虑您的需求/用例,但我认为自定义CacheManager可以在这种情况下工作,假设&#34; custom&#34; CacheManager逻辑是正确的。

因此,默认情况下, Spring 在上下文中查找名为&#34; cacheManager&#34;的bean。并将其用于所有缓存操作。在您的配置中,您显然拥有2&#34; CacheManagers&#34;定义...

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

    return new EventsCacheManager();
}

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

即。 &#34; eventsCacheManager&#34; (自定义)和&#34; cacheManager&#34; (标准)。实际上,您甚至标记了&#34; cacheManager&#34;作为主要(使用@Primary注释)。当然,如果你没有这样做, Spring 肯定会抱怨,因为在执行自动布线时,在上下文中找到了超过1个给定类型的bean(即CacheManager)(默认为按类型自动连接。)

因此,为了调出在运行时使用特定服务调用的缓存管理策略(即CacheManager),您还需要告诉 Spring {{1} }(又名策略)使用,像这样......

CacheManager

即。使用@Override @Cacheable(value = "concerts", cacheManager="eventsCacheManager") public List<Event> getEvents(String eventsForUser, Date startDate, Date endDate) throws Exception { return fetchEventsFromTheServer(eventsForUser, startDate, endDate); } 注释中的cacheManager属性来指示要使用的缓存策略。

有关详细信息,请参阅Custom cache resolution上的Spring的参考文档。

希望这有助于您前进。

答案 1 :(得分:1)

从我对你的问题的理解,我相信你是以错误的方式看问题。

您不必浏览缓存内容以提取派生信息,而应在加载主数据时将衍生信息插入缓存中。

例如,在加载基于月份的信息时,立即将其分解为基于日期的信息,并将其放入缓存中。

此描述还应清楚地表明您想要做的事情超出了Spring缓存抽象的功能,因为您需要自定义缓存加载逻辑。

因此我不建议攻击CacheManager来隐藏该逻辑,而是从数据加载逻辑中执行此操作。