Java 在没有 XML 的 Spring 4 中使用 EhCache
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21944202/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using EhCache in Spring 4 without XML
提问by Erich
Is there a way to initialize EhCache without xml in either Spring 4 or with Spring Boot?
有没有办法在 Spring 4 或 Spring Boot 中不用 xml 初始化 EhCache?
I noticed Spring Boot 1.0.0.RC3 doesn't have any ehcache dependencies but the Spring 4.0GA release postmentioned it has improved support for EhCache. Also, Spring 3 had the class org.springframework.cache.ehcache.EhCacheCacheManager
but that's no longer part of the dependencies.
我注意到 Spring Boot 1.0.0.RC3 没有任何 ehcache 依赖项,但Spring 4.0GA 发布帖子提到它改进了对 EhCache 的支持。此外,Spring 3 有这个类,org.springframework.cache.ehcache.EhCacheCacheManager
但它不再是依赖项的一部分。
Edit:Spring 4 does have EhCache support. You must add the dependency:
编辑:Spring 4 确实有 EhCache 支持。您必须添加依赖项:
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
Edit2:I've tried the following and I think I'm close but I'm getting an error:
Edit2:我尝试了以下操作,我想我已经接近了,但出现错误:
@Bean
@Override
public CacheManager cacheManager() {
CacheConfiguration cacheConfiguration = new CacheConfiguration();
cacheConfiguration.setName("primary");
cacheConfiguration.setMemoryStoreEvictionPolicy("LRU");
cacheConfiguration.setMaxEntriesLocalHeap(0);
net.sf.ehcache.config.Configuration config = new net.sf.ehcache.config.Configuration();
config.addCache(cacheConfiguration);
net.sf.ehcache.CacheManager cacheManager = new net.sf.ehcache.CacheManager(config);
cacheManager.setName("EhCache");
return new EhCacheCacheManager(cacheManager);
}
@Bean
public EhCacheManagerFactoryBean factoryBean() {
return new EhCacheManagerFactoryBean();
}
Error
错误
Caused by: net.sf.ehcache.CacheException: Another unnamed CacheManager already exists in the same VM. Please provide unique names for each CacheManager in the config or do one of following:
1. Use one of the CacheManager.create() static factory methods to reuse same CacheManager with same name or create one if necessary
2. Shutdown the earlier cacheManager before creating new one with same name.
The source of the existing CacheManager is: [Programmatically configured]
at net.sf.ehcache.CacheManager.assertNoCacheManagerExistsWithSameName(CacheManager.java:590)
at net.sf.ehcache.CacheManager.init(CacheManager.java:384)
at net.sf.ehcache.CacheManager.<init>(CacheManager.java:263)
at org.springframework.cache.ehcache.EhCacheManagerFactoryBean.afterPropertiesSet(EhCacheManagerFactoryBean.java:166)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549)
... 15 more
采纳答案by Erich
XML-less configuration of EhCache in Spring
Spring 中 EhCache 的无 XML 配置
@Configuration
@EnableCaching
public 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.
或者进行测试,您可以使用一个简单的 ConcurrentMapCache 运行而无需 XML,如下所示。
@Configuration
@EnableCaching
public 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+)
编辑:更改构造函数调用以SimpleCacheResolver
解决CacheManager must not be null
问题(Spring v5.1+)
@Configuration
@EnableCaching
public 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();
}
}
回答by Emerson Farrugia
I do this at two levels of abstraction, a configuration file per technology (Ehcache, Redis, etc.) and a general configuration file.
我在两个抽象级别上执行此操作,每个技术(Ehcache、Redis 等)的配置文件和通用配置文件。
Here's the one for Ehcache (Redis would be similar):
这是 Ehcache 的(Redis 类似):
@Configuration
public 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):
这是一般的(带有 Redis 钩子):
@Configuration
@EnableCaching
public 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();
}
}