Java Spring启动缓存预热

Java Spring启动缓存预热,java,spring,spring-boot,spring-cache,Java,Spring,Spring Boot,Spring Cache,我需要对spring缓存函数有一些基本的了解。我想按照计划bean构建一个缓存加热器和重新同步器,以便在发生更改时按需更新缓存 比如说,我有一个AccountClient和一个getAccount(stringid),它从一个非常慢的API获取一个帐户。所以基本上我能做到 @Cachable(cacheNames = "account", key = "#id", sync = true) public Account getAccount(String id) { //... } 一切

我需要对spring缓存函数有一些基本的了解。我想按照计划bean构建一个缓存加热器和重新同步器,以便在发生更改时按需更新缓存

比如说,我有一个
AccountClient
和一个
getAccount(stringid)
,它从一个非常慢的API获取一个
帐户。所以基本上我能做到

@Cachable(cacheNames = "account", key = "#id", sync = true)
public Account getAccount(String id) {
   //...
}
一切正常。现在我想预热缓存,而且,我得到了一个
getNewOrChangedAccounts()
,它从慢速数据存储中检索已更改帐户的ID

因此,我的方法如下:

public class AccountCacheManager {

    //...

    @Scheduled(initialDelay = 3000L, fixedRate = 10000L)
    public void sync() {
        List<Account> modifiedAccounts = accountClient.getNewOrChangedAccounts();

        modifiedAccounts.getAccounts().parallelStream()
                .forEach(account -> {
                   //delete old entry
                   evictAccount(account.getId());
                   //store new entry
                   putAccount(account.getId());

               });


        log.info("finished resync");
    }

    @CacheEvict(cacheNames = "account", key = "#id")
    public void evictAccount(String id) {
        log.debug("evicting account {}", id);
    }

    @CachePut(cacheNames = "account", key = "#id")
    public void putAccount(String id) {
        log.debug("storing account {}", id);
        accountService.getAccount(id);
    }
}
公共类AccountCacheManager{
//...
@计划(初始延迟=3000L,固定速度=10000L)
公共void sync(){
List modifiedAccounts=accountClient.getNewOrChangedAccounts();
modifiedAccounts.getAccounts().parallelStream()
.forEach(帐户->{
//删除旧条目
收回帐户(account.getId());
//存储新条目
putAccount(account.getId());
});
log.info(“完成重新同步”);
}
@cacheexecute(cacheNames=“account”,key=“#id”)
公共帐户(字符串id){
调试(“逐出帐户{}”,id);
}
@CachePut(cacheNames=“account”,key=“#id”)
公共帐户(字符串id){
调试(“存储帐户{}”,id);
accountService.getAccount(id);
}
}
所以我可以证明,这个过程开始了,并且做了一些事情。然而,当我点击我的API时,我看到第一次点击的是慢速后端,即使我的同步覆盖了后端的所有条目

我觉得我误解了spring缓存API的一些细节,那么我如何才能做到这一点呢

与@Cacheable注释不同,此注释不包含 导致跳过建议的方法。相反,它总是导致 方法,并将其结果存储在关联的 缓存

因此,用
@CachePut
注释的方法应将数据返回到缓存:

    @CachePut(cacheNames = "account", key = "#id")
    public Account putAccount(String id) {
        log.debug("storing account {}", id);
        return accountService.getAccount(id);
    }

另请参见此问题:

在引擎盖下,当类上声明了
@Cacheable
@CachePut
注释时,Spring会创建一个代理类,该类围绕从该类创建的bean实例

这个抽象缓存层只能通过该类外部的任何方法调用来使用

上述问题的简单解决方案是将cron方法分离到不同的类中,并通过注入bean调用缓存的方法

@组件
公共类AccountCacheManager{
//...
@CachePut(cacheNames=“account”,key=“#id”)
公共帐户putAccount(字符串id){
调试(“存储帐户{}”,id);
returnaccountservice.getAccount(id);
}
}
@组成部分
公共类CacheWarmupManager{
//这里注入的bean实际上是一个用缓存实现包装AccountCacheManager的代理
@自动连线私人帐户CacheManager accountManager;
@计划(初始延迟=3000L,固定速度=10000L)
公共void sync(){
List modifiedAccounts=accountClient.getNewOrChangedAccounts();
modifiedAccounts.getAccounts().parallelStream()
.forEach(帐户->{
//使用新条目强制更新缓存
accountManager.putcount(account.getId());
});
log.info(“完成重新同步”);
}
}
注意:
缓存预热cron方法无法工作的原因是该方法位于缓存方法的同一类上。因此,当cron触发时,它直接调用
putcount
executeaccount
方法,而不通过提供缓存的代理类

几天后,由于某些原因,它仍然不起作用……缓存是否对请求单独工作?直接使用
CacheManager
时,它看起来工作正常,仅仅用@CachePut和return注释是不够的