Spring:多个缓存管理器
Spring: Multiple Cache Managers
我在实施第二个缓存管理器时遇到问题。目前我正在使用 EhCache,它运行良好。另外,我想实现 Java 简单缓存。
我的 CacheConfiguration
看起来像这样:
CacheConfiguration.java
@Configuration
@EnableCaching
@AutoConfigureAfter(value = { MetricsConfiguration.class })
@AutoConfigureBefore(value = { WebConfigurer.class, DatabaseConfiguration.class })
public class CacheConfiguration {
private final javax.cache.configuration.Configuration<Object, Object> jcacheConfiguration;
public CacheConfiguration(JHipsterProperties jHipsterProperties) {
JHipsterProperties.Cache.Ehcache ehcache =
jHipsterProperties.getCache().getEhcache();
jcacheConfiguration = Eh107Configuration.fromEhcacheCacheConfiguration(
CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class,
ResourcePoolsBuilder.heap(ehcache.getMaxEntries()))
.withExpiry(Expirations.timeToLiveExpiration(Duration.of(ehcache.getTimeToLiveSeconds(), TimeUnit.SECONDS)))
.build());
}
/**
* EhCache configuration
*
* @return
*/
@Bean
@Primary
public JCacheManagerCustomizer cacheManagerCustomizer() {
return cm -> {
cm.createCache(com.david.coinlender.domain.News.class.getName(), jcacheConfiguration);
// ...More caches
}
/**
* Java Simple Cache configuration
* @return
*/
@Bean
@Qualifier("simpleCacheManager")
public CacheManager simpleCacheManager() {
SimpleCacheManager simpleCacheManager = new SimpleCacheManager();
simpleCacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("bitfinexAuthCache")));
return simpleCacheManager;
}
}
我想使用简单缓存来缓存对象。即:
@Cacheable(cacheManager = "simpleCacheManager", cacheNames = "bitfinexAuthCache", key = "#apiKey.apiKey")
private Exchange createBitfinexAuthenticatedExchange(ApiKeys apiKey) {
ExchangeSpecification exSpec = new BitfinexExchange().getDefaultExchangeSpecification();
exSpec.setApiKey(apiKey.getApiKey());
exSpec.setSecretKey(apiKey.getSecret());
Exchange bfx = ExchangeFactory.INSTANCE.createExchange(BitfinexExchange.class.getName());
bfx.applySpecification(exSpec);
return bfx;
}
但是,在服务器启动时 liquibase 给我一个错误提示:
Caused by: java.lang.IllegalStateException: All Hibernate caches should be created upfront. Please update CacheConfiguration.java to add com.david.coinlender.domain.News
at io.github.jhipster.config.jcache.NoDefaultJCacheRegionFactory.createCache(NoDefaultJCacheRegionFactory.java:37)
at org.hibernate.cache.jcache.JCacheRegionFactory.getOrCreateCache(JCacheRegionFactory.java:190)
at org.hibernate.cache.jcache.JCacheRegionFactory.buildEntityRegion(JCacheRegionFactory.java:113)
at org.hibernate.cache.spi.RegionFactory.buildEntityRegion(RegionFactory.java:132)
at org.hibernate.internal.CacheImpl.determineEntityRegionAccessStrategy(CacheImpl.java:439)
at org.hibernate.metamodel.internal.MetamodelImpl.initialize(MetamodelImpl.java:120)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:297)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:445)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:889)
... 25 common frames omitted
我正在为我的应用程序使用 Jhipster 框架。我在这个问题上搜索了几个小时,但还没有找到解决方案。
这个错误是因为配置错误吗?有人可以给我指出正确的方向吗?
For those that wish to establish a more direct relationship between @EnableCaching and the exact cache manager bean to be used, the CachingConfigurer callback interface may be implemented. Notice the @Override-annotated methods below:
还有一个使用 CachingConfigurer
并采用在 JCacheCacheConfiguration 上实施的方法的替代方案。
1- 在 CacheConfiguration
class 中实现 CachingConfigurer
接口。一种选择是从 JCacheConfigurerSupport
.
扩展
public class CustomCacheConfiguration extends JCacheConfigurerSupport {
2- 创建默认的 cacheManager
bean,因为这个 bean 是通过 CachingConfigurer
配置的,它将作为默认的 cacheManager
被检索,在这种情况下它可以被 hibernate 使用二级缓存,对于这种方法,cacheManagerCustomizer
将只是一种方法。像这样:
@Bean
@Override
public CacheManager cacheManager() {
javax.cache.CacheManager jCacheCacheManager = createCacheManager();
cacheManagerCustomizer().customize(jCacheCacheManager);
return new JCacheCacheManager(jCacheCacheManager);
}
private javax.cache.CacheManager createCacheManager() {
CachingProvider cachingProvider = Caching.getCachingProvider();
return cachingProvider.getCacheManager();
}
private JCacheManagerCustomizer cacheManagerCustomizer() {
return cm -> {
cm.createCache(org.demo.app.domain.User.class.getName(), jcacheConfiguration);
......
};
}
3- 创建 simpleCacheManager
bean
@Bean("simpleCacheManager")
public SimpleCacheManager simpleCacheManager() {
SimpleCacheManager simpleCacheManager = new SimpleCacheManager();
simpleCacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("bitfinexAuthCache")));
return simpleCacheManager;
}
- 为了定义将使用哪个
cacheManager
然后通过 @Cacheable(cacheManager = "simpleCacheManager", cacheNames = "bitfinexAuthCache")
定义它
这里是 CacheConfiguration
的完整定制。
@Configuration
@EnableCaching
@AutoConfigureAfter(value = { MetricsConfiguration.class })
@AutoConfigureBefore(value = { WebConfigurer.class, DatabaseConfiguration.class})
public class CacheConfiguration extends JCacheConfigurerSupport {
private final javax.cache.configuration.Configuration<Object, Object> jcacheConfiguration;
public CustomCacheConfiguration(JHipsterProperties jHipsterProperties) {
JHipsterProperties.Cache.Ehcache ehcache =
jHipsterProperties.getCache().getEhcache();
jcacheConfiguration = Eh107Configuration.fromEhcacheCacheConfiguration(
CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class,
ResourcePoolsBuilder.heap(ehcache.getMaxEntries()))
.withExpiry(Expirations.timeToLiveExpiration(Duration.of(ehcache.getTimeToLiveSeconds(), TimeUnit.SECONDS)))
.build());
}
@Bean
@Override
public CacheManager cacheManager() {
javax.cache.CacheManager jCacheCacheManager = createCacheManager();
cacheManagerCustomizer().customize(jCacheCacheManager);
return new JCacheCacheManager(jCacheCacheManager);
}
private javax.cache.CacheManager createCacheManager() {
CachingProvider cachingProvider = Caching.getCachingProvider();
return cachingProvider.getCacheManager();
}
private JCacheManagerCustomizer cacheManagerCustomizer() {
return cm -> {
cm.createCache(org.demo.app.domain.User.class.getName(), jcacheConfiguration);
cm.createCache(org.demo.app.domain.Authority.class.getName(), jcacheConfiguration);
cm.createCache(org.demo.app.domain.User.class.getName() + ".authorities", jcacheConfiguration);
cm.createCache(org.demo.app.domain.Company.class.getName(), jcacheConfiguration);
//cm.createCache(org.demo.app.domain.News.class.getName(), jcacheConfiguration);
};
}
@Bean("simpleCacheManager")
public SimpleCacheManager simpleCacheManager() {
SimpleCacheManager simpleCacheManager = new SimpleCacheManager();
simpleCacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("bitfinexAuthCache")));
return simpleCacheManager;
}
}
在JHipster中(我写的代码),其实有两层缓存。您有 Spring 缓存和 Hibernate 二级缓存。两者都使用相同的实际 Ehcache CacheManager
.
在您的例子中,您已将 Ehcache 替换为 Spring 的简单缓存。但是由于NoDefaultJCacheRegionFactory
还是配置在Hibernate上,所以Hibernate使用的还是Ehcache。但是定制器不再使用了。所以它失败了。
您想为 Spring 提供一个简单的缓存,为 Hibernate 使用 Ehcache。这意味着实际上不需要在 Spring.
中为 Ehcache 注册 bean
最简单的方法就是执行以下操作。
首先,在DatabaseConfiguration
中配置Ehcache。所以当 hibernate JCache 工厂检索它时,它会被正确配置。
public DatabaseConfiguration(Environment env, JHipsterProperties jHipsterProperties) {
this.env = env;
JHipsterProperties.Cache.Ehcache ehcache =
jHipsterProperties.getCache().getEhcache();
CachingProvider provider = Caching.getCachingProvider();
javax.cache.CacheManager cacheManager = provider.getCacheManager();
javax.cache.configuration.Configuration<Object, Object> jcacheConfiguration = Eh107Configuration.fromEhcacheCacheConfiguration(
CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class,
ResourcePoolsBuilder.heap(ehcache.getMaxEntries()))
.withExpiry(Expirations.timeToLiveExpiration(Duration.of(ehcache.getTimeToLiveSeconds(), TimeUnit.SECONDS)))
.build());
cacheManager.createCache(com.mycompany.myapp.domain.User.class.getName(), jcacheConfiguration);
cacheManager.createCache(com.mycompany.myapp.domain.Authority.class.getName(), jcacheConfiguration);
cacheManager.createCache(com.mycompany.myapp.domain.User.class.getName() + ".authorities", jcacheConfiguration);
}
然后,配置Spring缓存。
public class CacheConfiguration {
public CacheConfiguration() {
}
@Bean
public CacheManager cacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
Collection<Cache> caches = Arrays.asList(
new ConcurrentMapCache("mycache")
// ...
);
cacheManager.setCaches(caches);
return cacheManager;
}
}
我在实施第二个缓存管理器时遇到问题。目前我正在使用 EhCache,它运行良好。另外,我想实现 Java 简单缓存。
我的 CacheConfiguration
看起来像这样:
CacheConfiguration.java
@Configuration
@EnableCaching
@AutoConfigureAfter(value = { MetricsConfiguration.class })
@AutoConfigureBefore(value = { WebConfigurer.class, DatabaseConfiguration.class })
public class CacheConfiguration {
private final javax.cache.configuration.Configuration<Object, Object> jcacheConfiguration;
public CacheConfiguration(JHipsterProperties jHipsterProperties) {
JHipsterProperties.Cache.Ehcache ehcache =
jHipsterProperties.getCache().getEhcache();
jcacheConfiguration = Eh107Configuration.fromEhcacheCacheConfiguration(
CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class,
ResourcePoolsBuilder.heap(ehcache.getMaxEntries()))
.withExpiry(Expirations.timeToLiveExpiration(Duration.of(ehcache.getTimeToLiveSeconds(), TimeUnit.SECONDS)))
.build());
}
/**
* EhCache configuration
*
* @return
*/
@Bean
@Primary
public JCacheManagerCustomizer cacheManagerCustomizer() {
return cm -> {
cm.createCache(com.david.coinlender.domain.News.class.getName(), jcacheConfiguration);
// ...More caches
}
/**
* Java Simple Cache configuration
* @return
*/
@Bean
@Qualifier("simpleCacheManager")
public CacheManager simpleCacheManager() {
SimpleCacheManager simpleCacheManager = new SimpleCacheManager();
simpleCacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("bitfinexAuthCache")));
return simpleCacheManager;
}
}
我想使用简单缓存来缓存对象。即:
@Cacheable(cacheManager = "simpleCacheManager", cacheNames = "bitfinexAuthCache", key = "#apiKey.apiKey")
private Exchange createBitfinexAuthenticatedExchange(ApiKeys apiKey) {
ExchangeSpecification exSpec = new BitfinexExchange().getDefaultExchangeSpecification();
exSpec.setApiKey(apiKey.getApiKey());
exSpec.setSecretKey(apiKey.getSecret());
Exchange bfx = ExchangeFactory.INSTANCE.createExchange(BitfinexExchange.class.getName());
bfx.applySpecification(exSpec);
return bfx;
}
但是,在服务器启动时 liquibase 给我一个错误提示:
Caused by: java.lang.IllegalStateException: All Hibernate caches should be created upfront. Please update CacheConfiguration.java to add com.david.coinlender.domain.News
at io.github.jhipster.config.jcache.NoDefaultJCacheRegionFactory.createCache(NoDefaultJCacheRegionFactory.java:37)
at org.hibernate.cache.jcache.JCacheRegionFactory.getOrCreateCache(JCacheRegionFactory.java:190)
at org.hibernate.cache.jcache.JCacheRegionFactory.buildEntityRegion(JCacheRegionFactory.java:113)
at org.hibernate.cache.spi.RegionFactory.buildEntityRegion(RegionFactory.java:132)
at org.hibernate.internal.CacheImpl.determineEntityRegionAccessStrategy(CacheImpl.java:439)
at org.hibernate.metamodel.internal.MetamodelImpl.initialize(MetamodelImpl.java:120)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:297)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:445)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:889)
... 25 common frames omitted
我正在为我的应用程序使用 Jhipster 框架。我在这个问题上搜索了几个小时,但还没有找到解决方案。
这个错误是因为配置错误吗?有人可以给我指出正确的方向吗?
For those that wish to establish a more direct relationship between @EnableCaching and the exact cache manager bean to be used, the CachingConfigurer callback interface may be implemented. Notice the @Override-annotated methods below:
还有一个使用 CachingConfigurer
并采用在 JCacheCacheConfiguration 上实施的方法的替代方案。
1- 在 CacheConfiguration
class 中实现 CachingConfigurer
接口。一种选择是从 JCacheConfigurerSupport
.
public class CustomCacheConfiguration extends JCacheConfigurerSupport {
2- 创建默认的 cacheManager
bean,因为这个 bean 是通过 CachingConfigurer
配置的,它将作为默认的 cacheManager
被检索,在这种情况下它可以被 hibernate 使用二级缓存,对于这种方法,cacheManagerCustomizer
将只是一种方法。像这样:
@Bean
@Override
public CacheManager cacheManager() {
javax.cache.CacheManager jCacheCacheManager = createCacheManager();
cacheManagerCustomizer().customize(jCacheCacheManager);
return new JCacheCacheManager(jCacheCacheManager);
}
private javax.cache.CacheManager createCacheManager() {
CachingProvider cachingProvider = Caching.getCachingProvider();
return cachingProvider.getCacheManager();
}
private JCacheManagerCustomizer cacheManagerCustomizer() {
return cm -> {
cm.createCache(org.demo.app.domain.User.class.getName(), jcacheConfiguration);
......
};
}
3- 创建 simpleCacheManager
bean
@Bean("simpleCacheManager")
public SimpleCacheManager simpleCacheManager() {
SimpleCacheManager simpleCacheManager = new SimpleCacheManager();
simpleCacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("bitfinexAuthCache")));
return simpleCacheManager;
}
- 为了定义将使用哪个
cacheManager
然后通过@Cacheable(cacheManager = "simpleCacheManager", cacheNames = "bitfinexAuthCache")
定义它
这里是 CacheConfiguration
的完整定制。
@Configuration
@EnableCaching
@AutoConfigureAfter(value = { MetricsConfiguration.class })
@AutoConfigureBefore(value = { WebConfigurer.class, DatabaseConfiguration.class})
public class CacheConfiguration extends JCacheConfigurerSupport {
private final javax.cache.configuration.Configuration<Object, Object> jcacheConfiguration;
public CustomCacheConfiguration(JHipsterProperties jHipsterProperties) {
JHipsterProperties.Cache.Ehcache ehcache =
jHipsterProperties.getCache().getEhcache();
jcacheConfiguration = Eh107Configuration.fromEhcacheCacheConfiguration(
CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class,
ResourcePoolsBuilder.heap(ehcache.getMaxEntries()))
.withExpiry(Expirations.timeToLiveExpiration(Duration.of(ehcache.getTimeToLiveSeconds(), TimeUnit.SECONDS)))
.build());
}
@Bean
@Override
public CacheManager cacheManager() {
javax.cache.CacheManager jCacheCacheManager = createCacheManager();
cacheManagerCustomizer().customize(jCacheCacheManager);
return new JCacheCacheManager(jCacheCacheManager);
}
private javax.cache.CacheManager createCacheManager() {
CachingProvider cachingProvider = Caching.getCachingProvider();
return cachingProvider.getCacheManager();
}
private JCacheManagerCustomizer cacheManagerCustomizer() {
return cm -> {
cm.createCache(org.demo.app.domain.User.class.getName(), jcacheConfiguration);
cm.createCache(org.demo.app.domain.Authority.class.getName(), jcacheConfiguration);
cm.createCache(org.demo.app.domain.User.class.getName() + ".authorities", jcacheConfiguration);
cm.createCache(org.demo.app.domain.Company.class.getName(), jcacheConfiguration);
//cm.createCache(org.demo.app.domain.News.class.getName(), jcacheConfiguration);
};
}
@Bean("simpleCacheManager")
public SimpleCacheManager simpleCacheManager() {
SimpleCacheManager simpleCacheManager = new SimpleCacheManager();
simpleCacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("bitfinexAuthCache")));
return simpleCacheManager;
}
}
在JHipster中(我写的代码),其实有两层缓存。您有 Spring 缓存和 Hibernate 二级缓存。两者都使用相同的实际 Ehcache CacheManager
.
在您的例子中,您已将 Ehcache 替换为 Spring 的简单缓存。但是由于NoDefaultJCacheRegionFactory
还是配置在Hibernate上,所以Hibernate使用的还是Ehcache。但是定制器不再使用了。所以它失败了。
您想为 Spring 提供一个简单的缓存,为 Hibernate 使用 Ehcache。这意味着实际上不需要在 Spring.
中为 Ehcache 注册 bean最简单的方法就是执行以下操作。
首先,在DatabaseConfiguration
中配置Ehcache。所以当 hibernate JCache 工厂检索它时,它会被正确配置。
public DatabaseConfiguration(Environment env, JHipsterProperties jHipsterProperties) {
this.env = env;
JHipsterProperties.Cache.Ehcache ehcache =
jHipsterProperties.getCache().getEhcache();
CachingProvider provider = Caching.getCachingProvider();
javax.cache.CacheManager cacheManager = provider.getCacheManager();
javax.cache.configuration.Configuration<Object, Object> jcacheConfiguration = Eh107Configuration.fromEhcacheCacheConfiguration(
CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class,
ResourcePoolsBuilder.heap(ehcache.getMaxEntries()))
.withExpiry(Expirations.timeToLiveExpiration(Duration.of(ehcache.getTimeToLiveSeconds(), TimeUnit.SECONDS)))
.build());
cacheManager.createCache(com.mycompany.myapp.domain.User.class.getName(), jcacheConfiguration);
cacheManager.createCache(com.mycompany.myapp.domain.Authority.class.getName(), jcacheConfiguration);
cacheManager.createCache(com.mycompany.myapp.domain.User.class.getName() + ".authorities", jcacheConfiguration);
}
然后,配置Spring缓存。
public class CacheConfiguration {
public CacheConfiguration() {
}
@Bean
public CacheManager cacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
Collection<Cache> caches = Arrays.asList(
new ConcurrentMapCache("mycache")
// ...
);
cacheManager.setCaches(caches);
return cacheManager;
}
}