Can I set TTL for @Cacheable

I tried @Cacheable annotation support for Spring 3.1 and wonder if there is a way to make cached data cleared after a while by setting TTL? Right now, from what I see, I need to cleanse myself using @CacheEvict, and using this with @Scheduled, I can do the TTL implementation myself, but is it a bit similar for such a simple task?

+49
java spring
Nov 18 '11 at 11:34
source share
7 answers

See http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#cache-specific-config :

How to set TTL / TTI / Eviction policy / XXX function?

Directly through the cache provider. Cache abstraction ... well, abstraction is not a cache implementation

So, if you use EHCache, use the EHCache configuration to configure TTL.

You can also use Guava CacheBuilder to create a cache and pass that cache. View the ConcurrentMap in the setStore method of the ConcurrentMapCacheFactoryBean .

+24
Nov 18 '11 at 11:54
source share

Spring 3.1 and Guava 1.13.1:

@EnableCaching @Configuration public class CacheConfiguration implements CachingConfigurer { @Override public CacheManager cacheManager() { ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager() { @Override protected Cache createConcurrentMapCache(final String name) { return new ConcurrentMapCache(name, CacheBuilder.newBuilder().expireAfterWrite(30, TimeUnit.MINUTES).maximumSize(100).build().asMap(), false); } }; return cacheManager; } @Override public KeyGenerator keyGenerator() { return new DefaultKeyGenerator(); } } 
+24
Aug 29 2018-12-12T00:
source share

Here is a complete example of setting up a Guava cache in Spring. I used Guava over Ehcache because it is a bit lighter and the configuration seemed to me more direct.

Import Maven Dependencies

Add these dependencies to your maven mam file and do the cleanup and packages. These files are helper methods of Guava dep and Spring for use in CacheBuilder.

  <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>18.0</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.1.7.RELEASE</version> </dependency> 

Configure cache

You need to create a CacheConfig file to configure the cache using the Java configuration.

 @Configuration @EnableCaching public class CacheConfig { public final static String CACHE_ONE = "cacheOne"; public final static String CACHE_TWO = "cacheTwo"; @Bean public Cache cacheOne() { return new GuavaCache(CACHE_ONE, CacheBuilder.newBuilder() .expireAfterWrite(60, TimeUnit.MINUTES) .build()); } @Bean public Cache cacheTwo() { return new GuavaCache(CACHE_TWO, CacheBuilder.newBuilder() .expireAfterWrite(60, TimeUnit.SECONDS) .build()); } } 

Annotate method for caching

Add the @Cacheable annotation and pass the cache name.

 @Service public class CachedService extends WebServiceGatewaySupport implements CachedService { @Inject private RestTemplate restTemplate; @Cacheable(CacheConfig.CACHE_ONE) public String getCached() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity<String> reqEntity = new HttpEntity<>("url", headers); ResponseEntity<String> response; String url = "url"; response = restTemplate.exchange( url, HttpMethod.GET, reqEntity, String.class); return response.getBody(); } } 

Here you can see a more complete example with annotated screenshots: Guava Cache in Spring

+21
Aug 10 '15 at 18:37
source share

I use such a hacker hack

 @Configuration @EnableCaching @EnableScheduling public class CachingConfig { public static final String GAMES = "GAMES"; @Bean public CacheManager cacheManager() { ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager(GAMES); return cacheManager; } @CacheEvict(allEntries = true, value = {GAMES}) @Scheduled(fixedDelay = 10 * 60 * 1000 , initialDelay = 500) public void reportCacheEvict() { System.out.println("Flush Cache " + dateFormat.format(new Date())); } 
+14
Jul 08 '16 at 8:03
source share

Springboot 1.3.8

 import java.util.concurrent.TimeUnit; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.guava.GuavaCacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.google.common.cache.CacheBuilder; @Configuration @EnableCaching public class CacheConfig extends CachingConfigurerSupport { @Override @Bean public CacheManager cacheManager() { GuavaCacheManager cacheManager = new GuavaCacheManager(); return cacheManager; } @Bean public CacheManager timeoutCacheManager() { GuavaCacheManager cacheManager = new GuavaCacheManager(); CacheBuilder<Object, Object> cacheBuilder = CacheBuilder.newBuilder() .maximumSize(100) .expireAfterWrite(5, TimeUnit.SECONDS); cacheManager.setCacheBuilder(cacheBuilder); return cacheManager; } } 

and

 @Cacheable(value="A", cacheManager="timeoutCacheManager") public Object getA(){ ... } 
+11
Nov 24 '16 at 14:27
source share

Since Spring is boot-1.3.3, you can set the expiration time in CacheManager using RedisCacheManager.setExpires or RedisCacheManager.setDefaultExpiration in the CacheManagerCustomizer bean callback.

+1
Jul 12 '16 at 10:13
source share

this can be done by extending org.springframework.cache.interceptor.CacheInterceptor and overriding the doPut method - org.springframework.cache.interceptor.AbstractCacheInvoker your override logic should use the put provider cache method that knows to set the TTL to write to the cache (in In my case, I use HazelcastCacheManager)

 @Autowired @Qualifier(value = "cacheManager") private CacheManager hazelcastCacheManager; @Override protected void doPut(Cache cache, Object key, Object result) { //super.doPut(cache, key, result); HazelcastCacheManager hazelcastCacheManager = (HazelcastCacheManager) this.hazelcastCacheManager; HazelcastInstance hazelcastInstance = hazelcastCacheManager.getHazelcastInstance(); IMap<Object, Object> map = hazelcastInstance.getMap("CacheName"); //set time to leave 18000 secondes map.put(key, result, 18000, TimeUnit.SECONDS); } 

in your cache configuration, you need to add these 2 bean methods, creating your custom interceptor instance.

 @Bean public CacheOperationSource cacheOperationSource() { return new AnnotationCacheOperationSource(); } @Primary @Bean public CacheInterceptor cacheInterceptor() { CacheInterceptor interceptor = new MyCustomCacheInterceptor(); interceptor.setCacheOperationSources(cacheOperationSource()); return interceptor; } 

This solution is good if you want to set TTL at the entry level and not globally at the cache level.

+1
Feb 01 '17 at 11:59 on
source share



All Articles