Using EhCache in Spring 4 without XML
XML-less configuration of EhCache in Spring
@Configuration@EnableCachingpublic class CachingConfig implements CachingConfigurer { @Bean(destroyMethod="shutdown") public net.sf.ehcache.CacheManager ehCacheManager() { CacheConfiguration cacheConfiguration = new CacheConfiguration(); cacheConfiguration.setName("myCacheName"); cacheConfiguration.setMemoryStoreEvictionPolicy("LRU"); cacheConfiguration.setMaxEntriesLocalHeap(1000); net.sf.ehcache.config.Configuration config = new net.sf.ehcache.config.Configuration(); config.addCache(cacheConfiguration); return net.sf.ehcache.CacheManager.newInstance(config); } @Bean @Override public CacheManager cacheManager() { return new EhCacheCacheManager(ehCacheManager()); } @Bean @Override public KeyGenerator keyGenerator() { return new SimpleKeyGenerator(); } @Bean @Override public CacheResolver cacheResolver() { return new SimpleCacheResolver(); } @Bean @Override public CacheErrorHandler errorHandler() { return new SimpleCacheErrorHandler(); }}
Alternatively for testing, you can use a simple ConcurrentMapCache running without XML as below.
@Configuration@EnableCachingpublic class CachingConfig implements CachingConfigurer { @Bean @Override public CacheManager cacheManager() { SimpleCacheManager cacheManager = new SimpleCacheManager(); List<Cache> caches = new ArrayList<Cache>(); caches.add(new ConcurrentMapCache("myCacheName")); cacheManager.setCaches(caches); return cacheManager; } @Bean @Override public KeyGenerator keyGenerator() { return new SimpleKeyGenerator(); } @Bean @Override public CacheResolver cacheResolver() { return new SimpleCacheResolver(); } @Bean @Override public CacheErrorHandler errorHandler() { return new SimpleCacheErrorHandler(); }}
Edit: Updated to add shutdown method on underlying cache
Edit: Added configuration for error handler and cache resolver
Edit: changing constructor call on SimpleCacheResolver
which resolves CacheManager must not be null
issue (Spring v5.1+)
@Configuration@EnableCachingpublic class CachingConfig implements CachingConfigurer { public static final String USER_CACHE_INSTANCE = "my-spring-ehcache"; private final CacheManager cacheManager; private final net.sf.ehcache.CacheManager ehCacheManager; public CachingConfig() { CacheConfiguration cacheConfiguration = new CacheConfiguration(); cacheConfiguration.setName(USER_CACHE_INSTANCE); cacheConfiguration.setMemoryStoreEvictionPolicy("LRU"); cacheConfiguration.setMaxEntriesLocalHeap(1000); net.sf.ehcache.config.Configuration config = new net.sf.ehcache.config.Configuration(); config.addCache(cacheConfiguration); this.ehCacheManager = net.sf.ehcache.CacheManager.newInstance(config); this.cacheManager = new EhCacheCacheManager(ehCacheManager); } @Bean(destroyMethod="shutdown") public net.sf.ehcache.CacheManager ehCacheManager() { return ehCacheManager; } @Bean @Override public CacheManager cacheManager() { return cacheManager; } @Bean @Override public KeyGenerator keyGenerator() { return new SimpleKeyGenerator(); } @Bean @Override public CacheResolver cacheResolver() { return new SimpleCacheResolver(cacheManager); } @Bean @Override public CacheErrorHandler errorHandler() { return new SimpleCacheErrorHandler(); }}
I do this at two levels of abstraction, a configuration file per technology (Ehcache, Redis, etc.) and a general configuration file.
Here's the one for Ehcache (Redis would be similar):
@Configurationpublic class EhCacheConfiguration { @Bean public EhCacheCacheManager ehCacheCacheManager() { return new EhCacheCacheManager(ehCacheManagerFactoryBean().getObject()); } @Bean public EhCacheManagerFactoryBean ehCacheManagerFactoryBean() { EhCacheManagerFactoryBean cacheManagerFactoryBean = new EhCacheManagerFactoryBean(); cacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml")); cacheManagerFactoryBean.setShared(true); return cacheManagerFactoryBean; }}
And here's the general one (complete with Redis hooks):
@Configuration@EnableCachingpublic class CachingConfiguration implements CachingConfigurer { @Qualifier("ehCacheCacheManager") @Autowired(required = false) private CacheManager ehCacheCacheManager; @Qualifier("redisCacheManager") @Autowired(required = false) private CacheManager redisCacheManager; @Bean @Override public CacheManager cacheManager() { List<CacheManager> cacheManagers = Lists.newArrayList(); if (this.ehCacheCacheManager != null) { cacheManagers.add(this.ehCacheCacheManager); } if (this.redisCacheManager != null) { cacheManagers.add(this.redisCacheManager); } CompositeCacheManager cacheManager = new CompositeCacheManager(); cacheManager.setCacheManagers(cacheManagers); cacheManager.setFallbackToNoOpCache(false); return cacheManager; } @Bean @Override public KeyGenerator keyGenerator() { return new DefaultKeyGenerator(); }}