我在创建 Spring CacheManager 时遇到问题。当我尝试启动时,收到创建 bean 错误消息。
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@EnableCaching
@Configuration
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
log.trace("Creating cache manager.");
return new ConcurrentMapCacheManager("myCache");
}
}
我已经在日志行上放置了调试标记,但我没有到达它。在我们到达方法之前似乎就发生了一些事情。
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124)
at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:190)
at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:132)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:244)
at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:138)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$6(ClassBasedTestDescriptor.java:350)
...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cacheManager' defined in class path resource [org/chuck/config/CacheConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.cache.CacheManager]: Illegal arguments to factory method 'cacheManager'; args: ; nested exception is java.lang.IllegalArgumentException: object is not an instance of declaring class
解决方案(感谢 Nigel Savage)
不要命名班级
CacheConfig
对于 spring 类/bean 扫描,命名空间有一堆缓存注解[1]。
在这里,他们正在创建自己的用于缓存的配置 bean/类
CacheConfig
,这是一个典型的使用名称,并且具有类名 CacheConfig。
这里的问题是 Spring 开发人员有一个注释[1] @CacheConfig,它也有一个类名 CacheConfig。
从错误中可以看出,Spring CDI 上下文正在尝试通过 org.springframework.cache.CacheManager 类的 BeanFactory 代理[2] org.chuck.config.CacheConfig.class,该类具有引用 org.springframework.cache.CacheManager 的工厂方法。 springframework.cache.annotation.CacheConfig 类(在本例中是一个接口)
我认为只有当工厂不使用完全限定的类名时才会发生这种情况,我可以快速找到的唯一证据是此问题的评论[3]
简单的解决方案就是重命名自己的配置bean/类
[1] https://spring.io/guides/gs/caching/
[2] 你应该了解 CDI 如何使用代理类和范围启发式来创建对象,代理是运行时创建的 bean 的子类,我们可以在错误消息中得到提示
object is not an instance of declaring class
出于某种原因,SpringBoot 不会从 ehcache 库加载 CacheManager,因此解决方案是在项目中创建特定的 bean CacheManager。您可以按照Baeldung页面的相同方式进行操作。
https://www.baeldung.com/spring-boot-ehcache
这是一个示例:
package com.cache.ehcache.config;
import java.util.Arrays;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableCaching
@ComponentScan("com.cache.ehcache.service")
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
final SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("directory"), new ConcurrentMapCache("addresses")));
return cacheManager;
}
这对我有用。