【问题标题】:Unable to get cache from cachemanager unless cachemanager.getCacheNames() is invoked除非调用 cachemanager.getCacheNames() 否则无法从 cachemanager 获取缓存
【发布时间】:2019-02-18 22:10:39
【问题描述】:

我的应用程序使用 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");

我错过了什么?请帮我。

【问题讨论】:

    标签: spring ehcache spring-cache ehcache-3


    【解决方案1】:

    我的第一个问题是:“为什么不使用 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()));
    

    【讨论】:

    • 非常感谢您的回复。我想在我的应用程序中只定义一个配置了持久性目录的 CacheManager。如果 Spring 内置的 JCacheCacheManager 可以做到这一点,那么我很乐意使用它。我在另一个 bean 中以编程方式定义“foo”缓存。正如您猜到的那样,是的,我直接使用 EhCache 将它们定义为我的缓存需要的堆外存储。我将更新有关如何创建缓存的问题。
    • JCache 保留所有CacheManagers。因此,对于给定的 URI,您将始终得到相同的 URI。它是如何获得的并不重要。
    • 嗨@Henri,我已经用代码 sn-ps 更新了问题,解释了我的缓存是如何创建的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-14
    相关资源
    最近更新 更多