无法创建CacheManager bean

问题描述 投票:0回答:2

我在创建 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

java spring-boot spring-cache
2个回答
2
投票

对于 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

https://docs.spring.io/spring-javaconfig/docs/1.0.0.m3/reference/html/creating-bean-definitions.html
[3] https://github.com/spring-projects/spring-framework/issues/19229
“您当然可以为扫描指定自定义 BeanNameGenerator 并使用更独特的 bean 名称,例如完全限定的类名称。”


0
投票

出于某种原因,SpringBoot 不会从 ehcache 库加载 CacheManager,因此解决方案是在项目中创建特定的 bean CacheManager。您可以按照Baeldung页面的相同方式进行操作。

https://github.com/eugenp/tutorials/blob/master/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/config/CachingConfig.java

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;
    }

这对我有用。

© www.soinside.com 2019 - 2024. All rights reserved.