除非调用cachemanager.getCacheNames(),否则无法从cachemanager获取缓存

时间:2018-09-14 06:33:46

标签: spring ehcache spring-cache ehcache-3

我的应用程序使用Spring 4.3.x,EhCache 3.6和javax Cache 1.1.0。 这是我在应用程序中配置javax CacheManager的方式:

    <bean id="jCacheManager" class="org.springframework.cache.jcache.JCacheCacheManager">
        <property name="cacheManager" ref="appCacheManagerFactoryBean" />
    </bean>

    <bean id="appCacheManagerFactoryBean" class="com.example.AppCacheManagerFactoryBean"/>

AppCacheManagerFactoryBean(这只是JCacheManagerFactoryBean的自定义版本)可帮助我为我的应用程序配置全局持久性目录。这是它的外观:

public class AppCacheManagerFactoryBean implements FactoryBean<CacheManager>, InitializingBean,
    DisposableBean {

@Value("${cache.persistenceDir}")
private String persistenceDir;

private CacheManager cacheManager;

@Override
public void afterPropertiesSet() {
    this.cacheManager = buildCacheManager();
}

private CacheManager buildCacheManager()
{
    EhcacheCachingProvider cachingProvider = (EhcacheCachingProvider) Caching.getCachingProvider();
    DefaultConfiguration defaultConfiguration = new DefaultConfiguration(cachingProvider.getDefaultClassLoader(),
            new DefaultPersistenceConfiguration(new File(persistenceDir)));
    return cachingProvider.getCacheManager(cachingProvider.getDefaultURI(), defaultConfiguration);
}


@Override
public CacheManager getObject() {
    return this.cacheManager;
}

@Override
public Class<?> getObjectType() {
    return (this.cacheManager != null ? this.cacheManager.getClass() : CacheManager.class);
}

@Override
public boolean isSingleton() {
    return true;
}


@Override
public void destroy() {
    this.cacheManager.close();
}
}

这是我定义缓存的方式。我使用Ehcache API创建缓存,因为JCache API无法使用我的缓存所需的某些功能。

EhcacheManager ehcacheManager = jCacheCacheManager.getCacheManager().unwrap(EhcacheManager.class);
ehcacheManager.createCache("foo", CacheConfigurationBuilder.newCacheConfigurationBuilder(
                String.class, Foo.class,
                ResourcePoolsBuilder.newResourcePoolsBuilder()
                        .heap(1)
                        .offheap(1, MemoryUnit.GB)
                        .disk(5, MemoryUnit.GB)
        ));

当我尝试从应用程序中其他位置的CacheManager检索缓存时,会引发空指针异常。

Caching.getCachingProvider().getCacheManager().getCache("foo");

但是,如果在CacheManager中调用getCacheNames()方法后检索到缓存,则缓存将正常获取。

 Caching.getCachingProvider().getCacheManager().getCacheNames();
 Caching.getCachingProvider().getCacheManager().getCache("foo");

我错过了什么?请帮我。

1 个答案:

答案 0 :(得分:0)

我的第一个问题是:“为什么不使用Spring-cache的内置支持?”它不需要这样做。 JCacheCacheManager将负责所有工作。

然后,您的问题是高速缓存是直接在Ehcache中创建的,而没有通过JSR107层。调用getCacheNames()导致刷新JSR107中的缓存列表以使其起作用。但是,我不确定这种全局行为是故意的。但这是它的工作方式。

解决方案是按预期创建通过JSR107层的缓存。看起来像这样

CacheManager cacheManager = jcacheCacheManager.getCacheManager();
cacheManager.createCache("foo",
    Eh107Configuration.fromEhcacheCacheConfiguration(
        CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, Foo.class, ResourcePoolsBuilder.newResourcePoolsBuilder()
                    .heap(1)
                    .offheap(1, MemoryUnit.GB)
                    .disk(5, MemoryUnit.GB))
            .build()));