Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring可缓存注释在部署完成之前不起作用_Java_Spring_Caching_Couchbase - Fatal编程技术网

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

Java Spring可缓存注释在部署完成之前不起作用,java,spring,caching,couchbase,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 servic

我简化了下面的类和接口,以澄清问题

@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;
    }
}
Springbean负责在部署时加载缓存

@Component
class LoadCache {

    @Autowired
    private List<Loader> allLoaders;

    @PostConstruct
    public void load() {
        allLoaders.getCacheWrapper().getCallable().call();
    }
}
预加载元数据不会将数据保存在缓存中,但会执行。部署完成后,我再次调用相同的方法预加载元数据,然后将数据保存在缓存中

为什么@Cacheable在部署时不起作用

如果我手动使用缓存的put方法在带有@PostConstruct注释的方法中填充缓存,我就能够在部署时成功地完成这项工作

@Component
class LoadCache {

    @Autowired
    private List<Loader> allLoaders;

    @PostConstruct
    public void load() {
        allLoaders.getCacheWrapper().getCallable().call();
    }
}
我使用Tomcat作为服务器。
我在Spring cache抽象背后使用Couchbase cache。

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

@Component
public class CacheInitializer implements ApplicationListener<ContextRefreshedEvent>{

    @Autowired
    private List<Loader> allLoaders;

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

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


因此,响应TrimeExpRead事件的事件侦听注释是在这种情况下使用的最好的方法,它确保上下文已经启动,然后只加载缓存。

因为它在部署的中间。那么为什么要通过编程方式填充缓存呢?我喜欢你使用ApplicationListener的想法。但是你能解释一下为什么Cacheable不起作用吗?cacheManager已实例化,所有缓存都已就绪,但Cacheable无法工作。很可能由于bean仍处于初始化阶段,aspectj方面尚未启用。我们还可以使用@EventListenervalue=ContextRefreshedEvent.class注释,这将阻止实现ApplicationListener。但是我使用CTW,所以我想aspectj不会产生问题。