我正在使用Spring Cache,在这里传递一组键,返回的是实体列表。我想让缓存框架了解返回列表中的每个元素都将与相应的代码一起缓存。目前看来,键是整个列表,如果我在随后的调用中缺少键,它将尝试重新加载整个集合。
@Override @Cacheable(value = "countries") public List<Country> getAll(List<String>codes) { return countryDao.findAllInCodes(codes); }
另一个可能性是返回的是地图,类似地,我希望缓存足够智能,以仅查询以前从未查询过的项目,还可以使用键将每个项目缓存。
@Override @Cacheable(value = "countries") public Map<String,Country> getAllByCode(List<String>codes) { return countryDao.findAllInCodes(codes); }
假设国家/地区类别如下所示:
class Country{ String code; String fullName; long id; ... // getters setters constructurs etc.. }
Spring Cache有可能吗?
实际上,即使使用Spring的Caching Abstraction,也有可能,但不是现成的(OOTB)。本质上,你必须自定义Spring的缓存基础结构(下面进一步解释)
通过默认情况下,Spring的缓存架构采用全@Cacheable方法参数的参数作为缓存的“钥匙”,作为解释在这里。当然,你也可以自定义使用一个关键分辨率规划环境地政司表达或用自定义KeyGenerator实现,如解释在这里。
@Cacheable
KeyGenerator
尽管如此,这并不会将参数参数的集合或数组以及@Cacheable方法的返回值分解为单独的缓存项(即,基于数组/集合或Map的键/值对)。
为此,你需要一个Spring的 自定义实现CacheManager(取决于你的缓存策略/提供者)和Cache接口。
CacheManager
注意:具有讽刺意味的是,这将是我第三次回答几乎相同的问题,第一次在这里,然后在这里,现在在这里,:-)。无论如何…
我已经对此示例进行了更新/整理(有点)。
请注意,我的例子扩展和定制的ConcurrentMapCacheManager所提供的Spring框架本身。
从理论上说,你可以扩展/自定义任何CacheManager的实现,像Redis的公司在springRedis的数据,这里(源),或枢纽的GemFire的 CacheManager在spring数据的GemFire,这里(源)。的开源版本匹的GemFire是阿帕奇的Geode,其具有相应的弹簧数据的Geode项目,(来源的CacheManager在spring数据的Geode,这基本上等同于SD的GemFire)。当然,你可以将此技术应用于其他缓存提供程序… Hazelcast,Ehcache等。
但是,工作的真正实质是由Spring的Cache接口的自定义实现(或更具体地说,是基类)处理的 。
无论如何,希望从我的示例中,你将能够弄清楚在应用程序中需要做什么才能满足应用程序的缓存要求。