Spring可缓存注释在部署完成之前不起作用

时间:2017-01-18 14:18:05

标签: java spring caching couchbase

我有以下类和接口(为简化起见而简化)。

@Serivce
class Service1 {

    @Cacheable("cacheName")
    public Metadata preLoadMetadata() {
        // load data from database
    }
}

@Service
class Service2 implements Loader {

    @Autowired @Lazy
    private Service1 service1;

    @Overrride
    public CacheWrapper getCacheWrapper() {
        return new CacheWrapper(() -> service1.preLoadMetadata());
    }
}

interface Loader {
    CacheWrapper getCacheWrapper();
}

class CacheWrapper {

    private Callable callable;

    public CacheWrapper(Callable callable) {
         this.callable = callable;
    }

    public getCallable() {
         return callable;
    }
}

Spring bean负责在部署时加载缓存。

@Component
class LoadCache {

    @Autowired
    private List<Loader> allLoaders;

    @PostConstruct
    public void load() {
        allLoaders.getCacheWrapper().getCallable().call();
    }
}

preLoadMetadata()不会将数据保存在缓存中,但会执行。部署完成后,我再次调用相同的方法preLoadMetadata(),然后将数据保存在缓存中。

为什么@Cacheable在部署时无效?

如果我手动使用put Cache方法在@PostConstruct注释的方法中填充缓存,我可以在部署时成功完成。

我使用Tomcat作为服务器 我在Spring缓存抽象后面使用Couchbase缓存。

2 个答案:

答案 0 :(得分:1)

如果您想预加载缓存,我建议您使用一个ApplicationListener,它将在您的应用程序启动后执行:

@Component
public class CacheInitializer implements ApplicationListener<ContextRefreshedEvent>{

    @Autowired
    private List<Loader> allLoaders;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        allLoaders.getCacheWrapper().getCallable().call();
    }
}

答案 1 :(得分:0)

Cacheable注释不起作用的根本原因: 仅当afterSingletonsInstantiated()已实例化所有bean时,initialized方法才将BeanFactory标志设置为true。如果initialized标志为false,则不执行缓存操作。这里,在post构造内部,当我们开始预加载缓存时,LoadCache很可能不是要实例化的最后一个bean。因此,不执行缓存操作(使用缓存注释时)。

因此,响应EventListener的{​​{1}}注释是在这种情况下使用的最佳选择,它确保上下文已经开始,然后只加载缓存。