在@PostConstruct期间使用@Cacheable的Spring缓存不起作用 [英] Spring cache using @Cacheable during @PostConstruct does not work

查看:618
本文介绍了在@PostConstruct期间使用@Cacheable的Spring缓存不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

与spring框架中的提交有关 https://github.com/spring-projects/spring- framework / commit / 5aefcc802ef05abc51bbfbeb4a78b3032ff9eee3

related to the commit in spring framework https://github.com/spring-projects/spring-framework/commit/5aefcc802ef05abc51bbfbeb4a78b3032ff9eee3

初始化设置为从 afterPropertiesSet() afterSingletonsInstantiated()之后的阶段

简而言之
这可以防止在@PostConstruct用例中使用缓存时缓存工作。

In short: This prevents the caching to work when using it in a @PostConstruct use case.

更长的版本
这可以防止用于

Longer version: This prevents the use case where you would


  1. 在methodB上使用@Cacheable创建serviceB

  1. create serviceB with @Cacheable on a methodB

使用@PostConstruct创建serviceA,调用serviceB.methodB

create serviceA with @PostConstruct calling serviceB.methodB

@Component 
public class ServiceA{

@Autowired
private ServiceB serviceB;

@PostConstruct
public void init() {
    List<String> list = serviceB.loadSomething();
}


这导致org .springframework.cache.interceptor.CacheAspectSupport现在没有初始化,因此没有缓存结果。

This results in org.springframework.cache.interceptor.CacheAspectSupport not being initialised now and thus not caching the result.

protected Object execute(CacheOperationInvoker invoker, Object target, Method method, Object[] args) {
   // check whether aspect is enabled
   // to cope with cases where the AJ is pulled in automatically
   if (this.initialized) {
//>>>>>>>>>>>> NOT Being called
      Class<?> targetClass = getTargetClass(target);
      Collection<CacheOperation> operations = getCacheOperationSource().getCacheOperations(method, targetClass);
      if (!CollectionUtils.isEmpty(operations)) {
         return execute(invoker, new CacheOperationContexts(operations, method, args, target, targetClass));
      }
   }
//>>>>>>>>>>>> Being called
   return invoker.invoke();
}

我的解决方法是手动调用初始化方法:

My workaround is to manually call the initialisation method:

@Configuration
public class SomeConfigClass{

  @Inject
  private CacheInterceptor cacheInterceptor;

  @PostConstruct
  public void init() {
    cacheInterceptor.afterSingletonsInstantiated();
  }

这当然解决了我的问题,但它有副作用,只是存在调用2次(1个手册和1个按预期的框架)

This of course fixes my issue but does it have side effects other that just being called 2 times (1 manual and 1 by the framework as intended)

我的问题是:
这是一个安全的解决方法,因为初始提交者似乎只是使用afterPropertiesSet()

My question is: "Is this a safe workaround to do as the initial commiter seemed to have an issue with just using the afterPropertiesSet()"

推荐答案

正如Marten所说,你不应该使用任何一个 PostConstruct 阶段中的那些服务,因为您无法保证代理拦截器此时已完全启动。

As Marten said already, you are not supposed to use any of those services in the PostConstruct phase because you have no guarantee that the proxy interceptor has fully started at this point.

预加载缓存的最佳方法是监听 ContextRefreshedEvent (4.2中提供的更多支持)和在那里做工作。话虽如此,我知道可能并不清楚这种用法是否被禁止,所以我创建了 SPR -12700 改进文档。我不确定你指的是什么javadoc。

Your best shot at pre-loading your cache is to listen for ContextRefreshedEvent (more support coming in 4.2) and do the work there. That being said, I understand that it may not be clear that such usage is forbidden so I've created SPR-12700 to improve the documentation. I am not sure what javadoc you were referring to.

回答你的问题:不,这不是一个安全的解决方法。您之前使用的副作用(即它不应该工作,如果您的bean在 CacheInterceptor 之前初始化)您会遇到同样的问题旧版本的框架)。不要在自己的代码中调用这种低级基础结构。

To answer your question: no it's not a safe workaround. What you were using before worked by "side-effect" (i.e. it wasn't supposed to work, if your bean was initialized before the CacheInterceptor you would have the same problem with an older version of the framework). Don't call such low-level infrastructure in your own code.

这篇关于在@PostConstruct期间使用@Cacheable的Spring缓存不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆