使用AssertSame验证CacheBuilder创建的客户端实例问题求助
问题分析与解决方案
首先明确:你的assertSame预期是完全正确的——同一缓存key两次获取应该返回同一对象引用,测试失败说明缓存没有正常命中,核心问题出在缓存实现或测试逻辑中。
可能的原因及排查步骤
1. 缓存key不一致
两次调用newRetryingClient时传入的QUALIFIER可能看起来相同,但实际存在差异(比如大小写、空格、特殊字符,或者是不同的String实例但equals为true?不,Guava Cache的String key是基于equals判断的,所以只要equals为true就会命中)。
- 排查:在
newRetryingClient方法中添加日志,打印clientConfigQualifier的内容和hashCode,确认两次传入的key完全一致:System.out.println("Key: " + clientConfigQualifier + ", hashCode: " + clientConfigQualifier.hashCode());
2. newClient方法被调用了两次(缓存未写入)
如果newClient被调用两次,说明缓存没有成功存储第一次的结果,常见原因是:
newClient方法抛出了异常:Guava Cache的get方法中,如果supplier(即() -> newClient(...))抛出异常,会被包装为ExecutionException,此时不会将结果写入缓存,下次调用会重新执行supplier。- 排查:在
newClient方法中添加日志,确认是否被调用两次;同时检查newClient内部是否有隐藏的异常抛出(比如配置加载失败、资源初始化异常)。
- 排查:在
- 缓存实例被意外重置:如果
SERVICE_CLIENT_CACHE不是clientFactory的实例变量(比如是局部变量),或者clientFactory被多次创建(但你的测试中是同一个实例),会导致每次调用用的是不同的缓存。- 排查:在
clientFactory的构造函数中打印SERVICE_CLIENT_CACHE的hashCode,确认测试中使用的是同一个缓存实例。
- 排查:在
3. 类名拼写异常(测试结果暴露的细节)
你的测试结果显示两次返回的对象类名不同:clientImpl和clienttImpl(多了一个t),这说明newClient方法两次返回了不同类的实例,进一步佐证了newClient被调用了两次——只有缓存未命中时,才会每次都执行supplier生成新实例。
解决方案
- 确保缓存key完全一致:检查
QUALIFIER的定义,避免动态生成或拼写错误。 - 修复
newClient的异常问题:确保newClient方法能稳定返回实例,无隐藏异常;如果必须处理异常,可在supplier中捕获并返回默认实例,保证缓存能写入结果。 - 确认缓存实例唯一性:保证
SERVICE_CLIENT_CACHE是clientFactory的私有final实例变量,同一clientFactory实例复用同一个缓存。 - 验证缓存写入:在第一次调用
get后,手动调用SERVICE_CLIENT_CACHE.getIfPresent(clientConfigQualifier),检查是否能获取到缓存的实例。
内容的提问来源于stack exchange,提问作者pandabearit
相关产品推荐
相关产品推荐

