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不会产生问题。