Java 在可缓存方法类强制转换异常中调用Spring可缓存方法

Java 在可缓存方法类强制转换异常中调用Spring可缓存方法,java,spring,spring-cache,Java,Spring,Spring Cache,我试图使用Spring Cacheable,但遇到了类强制转换异常 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = CacheableTest.class, loader = AnnotationConfigContextLoader.class) @Configuration @EnableCaching public class CacheableTest { public static

我试图使用Spring Cacheable,但遇到了类强制转换异常

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CacheableTest.class, loader = AnnotationConfigContextLoader.class)
@Configuration
@EnableCaching
public class CacheableTest {
    public static final String CACHE = "cache";

    @Bean
    public CacheManager cacheManager() {
        return new ConcurrentMapCacheManager(CACHE);
    }

    @Autowired
    DataService service;

    @Test
    public void cacheTest() {
        final String name = "name";
        Data a = service.getData(name);
        Data b = service.getData(new String(name));
        Assert.assertSame(a, b);
        String c = service.getValue(service.getData(name));
        String d = service.getValue(service.getData(new String(name)));
        Assert.assertSame(c, d);
        String e = service.getValue(name);
        String f = service.getValue(new String(name));
        Assert.assertSame(e, f);
    }

    public static class Data {
        private String value;
        public Data(String value) {
            this.value = value;
        }
    }

    @Service
    public static class DataService {
        @Resource
        private DataService self;

        @Cacheable(CACHE)
        public Data getData(String name) {
            return new Data(name);
        }

        @Cacheable(CACHE)
        public String getValue(Data data) {
            return data.value;
        }

        @Cacheable(CACHE)
        public String getValue(String name) {
            return self.getData(name).value;
        }
    }

}

异常表示,
CacheableTest$数据不能转换为java.lang.String
,这发生在字符串e行。我们知道原因吗?

您声明了两个参数相同但返回类型不同的方法:

public Data getData(字符串名称)
公共字符串getValue(字符串名称)
您将它们都标记为具有相同缓存名称的
@Cacheable
。因此,您将共享单个缓存以存储两种方法的结果。两种方法都有完全相同的参数(
String
),因此spring为
数据
计算的缓存键将发生冲突

调用的第一个方法将返回spring将放入缓存的结果,第二个方法将尝试从缓存中检索相同的结果(因为缓存名称和方法参数匹配),并尝试将其转换为其他类型-因此,类转换异常

这和你做的差不多:

Map<String, Object> cache = new HashMap<>();
cache.put("key", "value1");
int i = (Integer)cache.get("key")
Map cache=newhashmap();
cache.put(“key”、“value1”);
int i=(整数)cache.get(“key”)

Ah好的。因此,默认情况下,
@Cacheable
仅检查输入参数以定位缓存结果。谢谢你回答“为什么”。你知道如何解决这个问题吗(例如,使
@Cacheable
组合返回类型+方法名称+输入参数作为唯一键来定位缓存)?我认为解决方案就是对不同类型使用单独的缓存。例如,您可以调用一个缓存
“dataCache”
另一个
“valueCache”
。我想不出任何好的理由将这两种类型的对象都保存在一个缓存中。至少这是我修复它的方式,它对我有效。你也可以做一个自定义的密钥生成器,但还没有做到。老实说,我上面的答案只是对发生了什么的最好猜测。我遇到了同样的问题,因此找到了这个问题。我找不到任何关于
@Cacheable
如何处理这个特定主题的详细spring文档。如果有人能给我指出,我很乐意在我的答案中链接到它,并在需要时修改它。