Spring 可缓存注释在部署完成之前不起作用
Spring cacheable annotation doesn't work before deployment completes
我有以下 类 和接口(为了清楚起见进行了简化)。
@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
在部署时不起作用?
如果我手动使用 Cache
的 put
方法在用 @PostConstruct
注释的方法中填充缓存,我可以在部署时成功完成。
我正在使用 Tomcat 作为服务器。
我在 Spring 缓存抽象之后使用 Couchbase 缓存。
如果您想预加载缓存,我建议您使用 ApplicationListener
,它会在您的应用程序启动后执行:
@Component
public class CacheInitializer implements ApplicationListener<ContextRefreshedEvent>{
@Autowired
private List<Loader> allLoaders;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
allLoaders.getCacheWrapper().getCallable().call();
}
}
Cacheable
注解不工作的根本原因:
afterSingletonsInstantiated()
方法仅在 BeanFactory
已实例化所有 bean 时才将 initialized
标志设置为 true。如果 initialized
标志为假,则不执行缓存操作。在这里,在 post 构造中,当我们启动 pre-loading 缓存时,很可能 LoadCache
不是最后一个要实例化的 bean。因此,不执行任何缓存操作(使用缓存注释时)。
因此,在这种情况下,响应 ContextRefreshEvent
的 EventListener
注释是最好的选择,它确保上下文已经启动,然后只加载缓存。
我有以下 类 和接口(为了清楚起见进行了简化)。
@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
在部署时不起作用?
如果我手动使用 Cache
的 put
方法在用 @PostConstruct
注释的方法中填充缓存,我可以在部署时成功完成。
我正在使用 Tomcat 作为服务器。
我在 Spring 缓存抽象之后使用 Couchbase 缓存。
如果您想预加载缓存,我建议您使用 ApplicationListener
,它会在您的应用程序启动后执行:
@Component
public class CacheInitializer implements ApplicationListener<ContextRefreshedEvent>{
@Autowired
private List<Loader> allLoaders;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
allLoaders.getCacheWrapper().getCallable().call();
}
}
Cacheable
注解不工作的根本原因:
afterSingletonsInstantiated()
方法仅在 BeanFactory
已实例化所有 bean 时才将 initialized
标志设置为 true。如果 initialized
标志为假,则不执行缓存操作。在这里,在 post 构造中,当我们启动 pre-loading 缓存时,很可能 LoadCache
不是最后一个要实例化的 bean。因此,不执行任何缓存操作(使用缓存注释时)。
因此,在这种情况下,响应 ContextRefreshEvent
的 EventListener
注释是最好的选择,它确保上下文已经启动,然后只加载缓存。