Configuring the Cache Storage

The cache abstraction provides several storage integration options. To use them, you need to declare an appropriate CacheManager (an entity that controls and manages Cache instances and that can be used to retrieve these for storage).

JDK ConcurrentMap-based Cache

The JDK-based Cache implementation resides under cn.taketoday.cache.concurrent package. It lets you use ConcurrentHashMap as a backing Cache store. The following example shows how to configure two caches:

<!-- simple cache manager -->
<bean id="cacheManager" class="cn.taketoday.cache.support.SimpleCacheManager">
  <property name="caches">
    <set>
      <bean class="cn.taketoday.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="default"/>
      <bean class="cn.taketoday.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="books"/>
    </set>
  </property>
</bean>

The preceding snippet uses the SimpleCacheManager to create a CacheManager for the two nested ConcurrentMapCache instances named default and books. Note that the names are configured directly for each cache.

As the cache is created by the application, it is bound to its lifecycle, making it suitable for basic use cases, tests, or simple applications. The cache scales well and is very fast, but it does not provide any management, persistence capabilities, or eviction contracts.

Ehcache-based Cache

Ehcache 3.x is fully JSR-107 compliant and no dedicated support is required for it. See JSR-107 Cache for details.

Caffeine Cache

Caffeine is a Java 8 rewrite of Guava’s cache, and its implementation is located in the cn.taketoday.cache.caffeine package and provides access to several features of Caffeine.

The following example configures a CacheManager that creates the cache on demand:

<bean id="cacheManager"
    class="cn.taketoday.cache.caffeine.CaffeineCacheManager"/>

You can also provide the caches to use explicitly. In that case, only those are made available by the manager. The following example shows how to do so:

<bean id="cacheManager" class="cn.taketoday.cache.caffeine.CaffeineCacheManager">
  <property name="cacheNames">
    <set>
      <value>default</value>
      <value>books</value>
    </set>
  </property>
</bean>

The Caffeine CacheManager also supports custom Caffeine and CacheLoader. See the Caffeine documentation for more information about those.

GemFire-based Cache

GemFire is a memory-oriented, disk-backed, elastically scalable, continuously available, active (with built-in pattern-based subscription notifications), globally replicated database and provides fully-featured edge caching. For further information on how to use GemFire as a CacheManager (and more).

JSR-107 Cache

Infra caching abstraction can also use JSR-107-compliant caches. The JCache implementation is located in the cn.taketoday.cache.jcache package.

Again, to use it, you need to declare the appropriate CacheManager. The following example shows how to do so:

<bean id="cacheManager"
    class="cn.taketoday.cache.jcache.JCacheCacheManager"
    p:cache-manager-ref="jCacheManager"/>

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

Dealing with Caches without a Backing Store

Sometimes, when switching environments or doing testing, you might have cache declarations without having an actual backing cache configured. As this is an invalid configuration, an exception is thrown at runtime, since the caching infrastructure is unable to find a suitable store. In situations like this, rather than removing the cache declarations (which can prove tedious), you can wire in a simple dummy cache that performs no caching — that is, it forces the cached methods to be invoked every time. The following example shows how to do so:

<bean id="cacheManager" class="cn.taketoday.cache.support.CompositeCacheManager">
  <property name="cacheManagers">
    <list>
      <ref bean="jdkCache"/>
      <ref bean="gemfireCache"/>
    </list>
  </property>
  <property name="fallbackToNoOpCache" value="true"/>
</bean>

The CompositeCacheManager in the preceding chains multiple CacheManager instances and, through the fallbackToNoOpCache flag, adds a no-op cache for all the definitions not handled by the configured cache managers. That is, every cache definition not found in either jdkCache or gemfireCache (configured earlier in the example) is handled by the no-op cache, which does not store any information, causing the target method to be invoked every time.