java - 如何在 Spring Java 配置中创建 Jcache?

标签 java spring spring-cache jcache caffeine

我在使用 spring cache abstraction 设置 jcache 时遇到问题.

@Configuration
@EnableCaching
public class CacheConfig {

    @Bean(name = "caffeineCachingProvider")
    public CachingProvider caffeineCachingProvider() {
        return new CaffeineCachingProvider();
    }

    @Bean(name = "caffeineCacheManager")
    public JCacheCacheManager getSpringCacheManager() {
        CacheManager cacheManager = caffeineCachingProvider().getCacheManager();
        CaffeineConfiguration<String, List<Product>> caffeineConfiguration = new CaffeineConfiguration<>();
        caffeineConfiguration.setExpiryPolicyFactory(FactoryBuilder.factoryOf(new AccessedExpiryPolicy(new Duration(TimeUnit.MINUTES, 60))));
        Cache<String, List<Product>> productCache = cacheManager.createCache("productCache", caffeineConfiguration);

        JCacheCacheManager jCacheCacheManager = new JCacheCacheManager(cacheManager);
        return jCacheCacheManager;
    }

} 

我正在使用 Caffein作为 Jcache。我只是不明白我做错了什么。你能解释一下如何正确地做到这一点吗?

我得到的是 NPE 在行 cacheManager.createCache(...)

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'caffeineCacheManager' defined in com.myapp.spring.config.CacheConfig: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.cache.jcache.JCacheCacheManager]: Factory method 'getSpringCacheManager' threw exception; nested exception is java.lang.NullPointerException
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1123)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
    at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:668)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:634)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:682)
    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:553)
    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:494)
    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
    at javax.servlet.GenericServlet.init(GenericServlet.java:158)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1284)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1197)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1087)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5266)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5554)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652)
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:677)
    at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1912)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.cache.jcache.JCacheCacheManager]: Factory method 'getSpringCacheManager' threw exception; nested exception is java.lang.NullPointerException
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
    ... 34 more
Caused by: java.lang.NullPointerException
    at com.github.benmanes.caffeine.jcache.CacheProxy.<init>(CacheProxy.java:109)
    at com.github.benmanes.caffeine.jcache.CacheFactory$Builder.newCacheProxy(CacheFactory.java:160)
    at com.github.benmanes.caffeine.jcache.CacheFactory$Builder.build(CacheFactory.java:145)
    at com.github.benmanes.caffeine.jcache.CacheFactory.createCache(CacheFactory.java:82)
    at com.github.benmanes.caffeine.jcache.CacheManagerImpl.lambda$createCache$0(CacheManagerImpl.java:98)
    at com.github.benmanes.caffeine.jcache.CacheManagerImpl$$Lambda$23/388708304.apply(Unknown Source)
    at java.util.concurrent.ConcurrentHashMap.compute(ConcurrentHashMap.java:1853)
    at com.github.benmanes.caffeine.jcache.CacheManagerImpl.createCache(CacheManagerImpl.java:94)
    at com.myapp.spring.config.CacheConfig.getSpringCacheManager(CacheConfig.java:55)
    at com.myapp.spring.config.CacheConfig$$EnhancerBySpringCGLIB$$4f46e611.CGLIB$getSpringCacheManager$1(<generated>)
    at com.myapp.spring.config.CacheConfig$$EnhancerBySpringCGLIB$$4f46e611$$FastClassBySpringCGLIB$$b70e5f67.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:355)
    at com.myapp.spring.config.CacheConfig$$EnhancerBySpringCGLIB$$4f46e611.getSpringCacheManager(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
    ... 35 more

最佳答案

阅读更多关于 Caffeine 配置的信息。它的 JCache 适配器使用默认规范 (JCache) 设置,该设置声明条目永不过期并按值存储(在从缓存中放入/检索时复制)。 (reference here)。

当缓存设置为复制实例时,您应该选择适当的 Copier 来处理它。所以你可以写:

caffeineConfiguration.setCopierFactory(JavaSerializationCopier::new);

caffeineConfiguration.setCopierFactory(Copier::identity);

这取决于您是否希望在缓存键/值突变的情况下保持安全。

不过,推荐的选项是使用 default settings其中 store-by-value 选项被禁用并且需要复印机:

Config config = ConfigFactory.load();
CaffeineConfiguration<String, List<Product>> caffeineConfiguration = TypesafeConfigurator.defaults(config);
caffeineConfiguration.setExpiryPolicyFactory(factoryOf(new AccessedExpiryPolicy(new Duration(
            TimeUnit.MINUTES, 60))));

或者,您可以通过以下方式禁用store-by-value设置:

caffeineConfiguration.setStoreByValue(false);

关于java - 如何在 Spring Java 配置中创建 Jcache?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34809817/

相关文章:

java - 使用@Cacheable的Spring缓存在启动时不起作用@PostConstruct

java - Java中检查数组是否旋转的方法?

java - Spring xml到java配置: how to convert nested xml bean definition

java - Ibatis startBatch() 仅适用于 SqlMapClient 自己的启动和提交事务,不适用于 Spring 管理的事务

java - tomcat服务器启动报错

java - Spring Boot 缓存 SpEL (#result) 返回 Null

java - Cordova - Android 上的 XHR 请求在模拟器中工作,但在手机上不工作

java - 为什么我的出列方法不适用于我的 treeMap PriceQueue?

java - 针对不同版本的 Java 代码或预处理进行细微更改?

java - 调用@Cacheable注解的方法(org.springframework.cache.annotation.Cacheable)