Java 使用@Cacheable的Spring缓存在启动@PostConstruct时不工作
我正在使用Spring,我想在启动应用程序之前缓存一些数据 我在其他帖子中找到了一些解决方案,使用@PostConstruct调用我的@Service方法(注释为@Cacheable),例如。 我这样做了,但在应用程序启动后,我调用REST端点,该端点再次调用此服务方法,它在另一次发送数据库请求(所以它还没有被缓存)。当我向端点发送第二次缓存数据的请求时 结论是,在@PostConstruct上调用服务方法不会导致缓存数据库中的数据 是否可以在启动应用程序之前缓存数据?我该怎么做?下面是我的代码片段Java 使用@Cacheable的Spring缓存在启动@PostConstruct时不工作,java,spring,caching,spring-cache,Java,Spring,Caching,Spring Cache,我正在使用Spring,我想在启动应用程序之前缓存一些数据 我在其他帖子中找到了一些解决方案,使用@PostConstruct调用我的@Service方法(注释为@Cacheable),例如。 我这样做了,但在应用程序启动后,我调用REST端点,该端点再次调用此服务方法,它在另一次发送数据库请求(所以它还没有被缓存)。当我向端点发送第二次缓存数据的请求时 结论是,在@PostConstruct上调用服务方法不会导致缓存数据库中的数据 是否可以在启动应用程序之前缓存数据?我该怎么做?下面是我的代码
@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");
}
}
@RestController
类MyController{
私有静态最终记录器Logger=LoggerFactory.getLogger(MyController.class);
@自动连线
我的服务;
@施工后
void init(){
调试(“MyController@PostConstruct启动”);
MyObject o=service.myMethod(“someString”);
logger.debug(“@PostConstruct:+o”);
}
@GetMapping(value=“api/{param}”)
MyObject myEndpoint(@PathVariable字符串参数){
返回服务.myMethod(param);
}
}
@服务
@CacheConfig(cacheNames=“myCache”)
类MyServiceImpl实现MyService{
@自动连线
MyDAO道;
@可缓存(key=“{#param}”)
@凌驾
公共MyObject myMethod(字符串参数){
返回dao.findByParam(param);
}
}
接口MyService{
MyObject myMethod(字符串参数);
}
@存储库
接口MyDAO扩展了JpaRepository{
MyObject findByParam(字符串参数);
}
@SpringBoot应用程序
@EnableConfigurationProperties
@启用缓存
公共类MyApplication{
公共静态void main(字符串[]args){
run(MyApplication.class,args);
}
@初级的
@豆子
公共缓存管理器jdkCacheManager(){
返回新的ConcurrentMapCacheManager(“myCache”);
}
}
@PostConstruct适用于您的情况。在实例化方法bean之后,将调用带有@PostConstruct注释的方法
但是,如果您依赖于其他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
}
}
@组件
公共类MyListener
实现ApplicationListener{
ApplicationEvent(ContextRefreshedEvent事件)上的公共无效{
//这里调用缓存的方法
//应用程序上下文完全启动后,将调用methode
}
}
尝试使用应用程序启动事件
而不是@PostConstruct
注释
我也有同样的问题,这个小零钱就解决了
你应该加上
@EventListener(classes=ApplicationStartedEvent.class)
在你的方法和通行证之上
ApplicationStartedEvent事件
作为一个参数
例如:
@EventListener(classes = ApplicationStartedEvent.class)
void init(ApplicationStartedEvent event) {
MyObject o = service.myMethod("someString");
}
在
@PostConstruct
中尝试这样做通常是一个坏主意,它可能会提前运行(没有创建代理,因此没有应用AOP)。最好在侦听ContextRefreshedEvent
s的ApplicationListener中执行类似操作。这是一个触发器,告诉您一切都已启动,您现在可以调用缓存方法。@M.Deinum ok,但我需要在REST端点启动和侦听请求之前启动缓存。我该怎么做?调度员服务一启动,它就开始监听。。。如上所述,使用ApplicationListener
以获得安全的方式。@M.Deinum谢谢,这解决了我的问题!