[已解決] nested exception is java.lang.IllegalStateException: refreshAfterWrite requires a LoadingCache異常解決
問題描述:
SpringBoot項目使用Caffeine緩存,出現如下異常信息:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cache' defined in class path resource [com/copyfuture/web/copyfutureweb/configurer/CacheConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.github.benmanes.caffeine.cache.Cache]: Factory method 'cache' threw exception; nested exception is java.lang.IllegalStateException: refreshAfterWrite requires a LoadingCache
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:627)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:607)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1305)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1144)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:849)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:127)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:117)
... 24 more
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.github.benmanes.caffeine.cache.Cache]: Factory method 'cache' threw exception; nested exception is java.lang.IllegalStateException: refreshAfterWrite requires a LoadingCache
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:622)
... 42 more
Caused by: java.lang.IllegalStateException: refreshAfterWrite requires a LoadingCache
at com.github.benmanes.caffeine.cache.Caffeine.requireState(Caffeine.java:194)
at com.github.benmanes.caffeine.cache.Caffeine.requireNonLoadingCache(Caffeine.java:1015)
at com.github.benmanes.caffeine.cache.Caffeine.build(Caffeine.java:921)
at com.copyfuture.web.copyfutureweb.configurer.CacheConfig.cache(CacheConfig.java:58)
at com.copyfuture.web.copyfutureweb.configurer.CacheConfig$$EnhancerBySpringCGLIB$$600e6612.CGLIB$cache$0(<generated>)
at com.copyfuture.web.copyfutureweb.configurer.CacheConfig$$EnhancerBySpringCGLIB$$600e6612$$FastClassBySpringCGLIB$$ac98c0d2.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363)
at com.copyfuture.web.copyfutureweb.configurer.CacheConfig$$EnhancerBySpringCGLIB$$600e6612.cache(<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:498)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
... 43 more
關鍵信息:
Factory method 'cache' threw exception; nested exception is java.lang.IllegalStateException: refreshAfterWrite requires a LoadingCache
原因
因為我使用的是refreshAfterWrite配置。
必須指定一個CacheLoader。不用該配置則無需這個bean,如上所述,該CacheLoader將關聯被該緩存管理器管理的所有緩存,所以必須定義為CacheLoader
解決方案
- 在構建LoadingCache對象的時候 build()方法中指定過期之後的加載策略方法
代碼:
public class CacheConfig {
/**
* 相當於在構建LoadingCache對象的時候 build()方法中指定過期之後的加載策略方法
* 必須要指定這個Bean,refreshAfterWrite=60s屬性才生效
* @return
*/
@Bean
public CacheLoader<String, Object> cacheLoader() {
CacheLoader<String, Object> cacheLoader = new CacheLoader<String, Object>() {
@Override
public Object load(String key) throws Exception {
return null;
}
// 重寫這個方法將oldValue值返回回去,進而刷新緩存
@Override
public Object reload(String key, Object oldValue) throws Exception {
return oldValue;
}
};
return cacheLoader;
}
@Bean
public Cache<String, Object> cache(CacheLoader<String, Object> cacheLoader) {
return Caffeine.newBuilder()
// 創建緩存或者最近一次更新緩存後經過固定的時間間隔,刷新緩存 最後一次寫入後經過固定時間過期
.refreshAfterWrite(3600L, TimeUnit.SECONDS)
// 初始的緩存空間大小
.initialCapacity(100)
// 緩存的最大條數
.maximumSize(100000)
//軟引用
.softValues()
.build(cacheLoader);
}
}
其中CacheLoader必須要有,在cache方法中進行指定過期之後的加載策略方式,也就是build(cacheLoader)。
作者:諳憶
地址:https://chenhx.blog.csdn.net/