使用@Cacheable 的Spring 缓存在启动@PostConstruct 时不起作用
Posted
技术标签:
【中文标题】使用@Cacheable 的Spring 缓存在启动@PostConstruct 时不起作用【英文标题】:Spring cache using @Cacheable not working on startup @PostConstruct 【发布时间】:2017-06-01 15:41:14 【问题描述】:我正在使用 Spring,我想在启动我的应用程序之前缓存一些数据。
我在其他帖子中找到了一些使用@PostConstruct 调用我的@Service 方法(注解为@Cacheable)的解决方案,例如。 How to load @Cache on startup in spring? 我这样做了,但是当应用程序启动后我调用 REST 端点,它再次调用此服务方法,它再次发送数据库请求(所以它还没有被缓存)。当我第二次向端点发送请求时,数据被缓存。
结论是在@PostConstruct 上调用Service 方法并没有导致从数据库缓存数据。
是否可以在启动应用程序之前缓存数据?我怎样才能做到这一点?下面是我的代码片段。
@RestController
class MyController
private static final Logger logger = LoggerFactory.getLogger(MyController.class);
@Autowired
MyService service;
@PostConstruct
void init()
logger.debug("MyController @PostConstruct started");
MyObject o = service.myMethod("someString");
logger.debug("@PostConstruct: " + o);
@GetMapping(value = "api/param")
MyObject myEndpoint(@PathVariable String param)
return service.myMethod(param);
@Service
@CacheConfig(cacheNames = "myCache")
class MyServiceImpl implements MyService
@Autowired
MyDAO dao;
@Cacheable(key = " #param ")
@Override
public MyObject myMethod(String param)
return dao.findByParam(param);
interface MyService
MyObject myMethod(String param);
@Repository
interface MyDAO extends JpaRepository<MyObject, Long>
MyObject findByParam(String param);
@SpringBootApplication
@EnableConfigurationProperties
@EnableCaching
public class MyApplication
public static void main(String[] args)
SpringApplication.run(MyApplication.class, args);
@Primary
@Bean
public CacheManager jdkCacheManager()
return new ConcurrentMapCacheManager("myCache");
【问题讨论】:
尝试在@PostConstruct
中执行此操作通常是一个坏主意,它可能会过早运行(没有创建代理,因此没有应用 AOP)。最好在侦听ContextRefreshedEvent
s 的ApplicationListener
中执行此类操作。那就是告诉你一切都已经开始的触发器,你现在可以调用缓存方法了。
@M.Deinum 好的,但我需要在启动 REST 端点并侦听请求之前启动缓存。我该怎么做?
一旦 dispatcherservlet 启动,它就会在监听...如前所述,使用ApplicationListener
以确保安全。
@M.Deinum 谢谢,这解决了我的问题!
【参考方案1】:
尝试使用ApplicationStartedEvent
代替@PostConstruct
注释。
我遇到了同样的问题,这个小改动解决了它。
你应该添加
@EventListener(classes = ApplicationStartedEvent.class)
在您的方法之上并通过
ApplicationStartedEvent event
作为参数。
例子:
@EventListener(classes = ApplicationStartedEvent.class)
void init(ApplicationStartedEvent event)
MyObject o = service.myMethod("someString");
【讨论】:
【参考方案2】:@PostConstruct 将适用于您的情况。带有@PostConstruct 注解的方法将在方法bean 被实例化后立即被调用。
但是,如果您依赖于其他 bean,并且您在应用程序上下文完全启动后调用您的方法?你可以像这样创建一个新的bean:
@Component
public class MyListener
implements ApplicationListener<ContextRefreshedEvent>
public void onApplicationEvent(ContextRefreshedEvent event)
//Here call your method of cache
// Your methode will be called after the application context has fully started
【讨论】:
以上是关于使用@Cacheable 的Spring 缓存在启动@PostConstruct 时不起作用的主要内容,如果未能解决你的问题,请参考以下文章
详解Spring缓存注解@Cacheable,@CachePut , @CacheEvict使用
使用@Cacheable 的Spring 缓存在启动@PostConstruct 时不起作用