Spring @Cacheable 对 @Scope("prototype") 实例唯一

Posted

技术标签:

【中文标题】Spring @Cacheable 对 @Scope("prototype") 实例唯一【英文标题】:Spring @Cacheable unique to a @Scope("prototype") instance 【发布时间】:2021-12-30 07:52:57 【问题描述】:

在我的 Spring Boot 应用程序中,我有一个从外部 API 检索数据的服务。它使用@Scope("prototype"),因为它经常调用几个不同的环境(例如,用于在 x 和 y 之间传输数据)。

@Component
@Scope("prototype")
public class ExternalAppConnection 
    private final URI uri;
    private final String sessionToken;

    public ExternalAppConnection(final String uri, final String sessionToken) 
        this.uri = new URI(uri);
        this.sessionToken = sessionToken;
    

    @Cacheable
    public AppInfoResponseDto getAppInfo(Integer appId) 
        String url = buildUrl("/api/appinfo" + appId);
        return exchangeRequestForObject(url, HttpMethod.GET, AppInfoResponseDto.class);
    

如上所示,服务的每个实例都有一个唯一的sessionTokenuri。不管实例如何,这里的@Cacheable 都会产生相同的缓存,因此在为一个环境调用getAppInfo() 后,如果appId 匹配,我会在为另一个环境调用它时得到一个缓存结果。

是否可以包含每个实例的缓存?我研究过使用CacheResolver,但上下文没有提供有关实例的任何详细信息,例如它的 sessionToken 或 uri。

【问题讨论】:

【参考方案1】:

使用custom KeyGenerator 将值放入单个缓存中,该缓存还可以通过urisessionToken 区分键。

public class CustomKeyGenerator extends SimpleKeyGenerator 

    @Override
    public Object generate(Object target, Method method, Object... params) 
        ExternalAppConnection externalAppConnection = (ExternalAppConnection) target;
        return generateKey(
                externalAppConnection.getUri(),
                externalAppConnection.getSessionToken(),
                params);
    

【讨论】:

以上是关于Spring @Cacheable 对 @Scope("prototype") 实例唯一的主要内容,如果未能解决你的问题,请参考以下文章

@cacheable的缓存怎么使用

spring 中的@cacheable的key是怎么配置的

详解Spring缓存注解@Cacheable,@CachePut , @CacheEvict使用

Spring缓存注解@Cacheable@CacheEvict@CachePut使用

Spring Boot缓存注解@Cacheable@CacheEvict@CachePut使用

Spring缓存注解@Cache,@CachePut , @CacheEvict,@CacheConfig使用