简体   繁体   English

使用 @Cacheable 的 Spring 缓存在启动时不起作用 @PostConstruct

[英]Spring cache using @Cacheable not working on startup @PostConstruct

I'm using Spring and I would like to cache some data before starting my app.我正在使用 Spring,我想在启动我的应用程序之前缓存一些数据。

I found some solutions in other posts to use @PostConstruct to call my @Service method (which are annotated @Cacheable), eg.我在其他帖子中找到了一些使用@PostConstruct 来调用我的@Service 方法(注释为@Cacheable)的解决方案,例如。 How to load @Cache on startup in spring? 如何在春季启动时加载@Cache? I did that but when after application start I call REST endpoint which calls this service method again it's sending database request another time (so it's not cached yet).我这样做了,但是当应用程序启动后,我调用 REST 端点,它再次调用此服务方法,它再次发送数据库请求(因此它尚未缓存)。 When I send request to endpoint for the second time data is cached.当我第二次向端点发送请求时,数据被缓存。

Conclusion is that calling Service method on @PostConstruct didn't cause caching data from database.结论是在@PostConstruct 上调用 Service 方法不会导致从数据库缓存数据。

Is it possible to cache data before starting app?是否可以在启动应用程序之前缓存数据? How can I do that?我怎样才能做到这一点? Below is my code fragments.下面是我的代码片段。

@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");
    }
}

Try using ApplicationStartedEvent instead of @PostConstruct annotation.尝试使用ApplicationStartedEvent而不是@PostConstruct注释。

I had the same problem and this small change fixed it.我遇到了同样的问题,这个小改动修复了它。

You should add @EventListener(classes = ApplicationStartedEvent.class) on top of your method and pass ApplicationStartedEvent event as a parameter.您应该在方法@EventListener(classes = ApplicationStartedEvent.class)添加@EventListener(classes = ApplicationStartedEvent.class)并将ApplicationStartedEvent event作为参数传递。

Example:例子:

@EventListener(classes = ApplicationStartedEvent.class)
void init(ApplicationStartedEvent event) {
    MyObject o = service.myMethod("someString");
}

@PostConstruct will work in your case. @PostConstruct 将适用于您的情况。 the method with @PostConstruct annotation will be called just after the method bean was instantiated.带有@PostConstruct 注释的方法将在方法 bean 实例化后立即调用。

But if you depend on other beans and you went your method to be called after the application context has fully started?但是,如果您依赖其他 bean 并且在应用程序上下文完全启动后调用您的方法? you can create a new bean like that :你可以像这样创建一个新的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
    }
}

With Spring 1.3 and later : 在Spring 1.3及更高版本中:

@Component
public class ApplicationStartup implements ApplicationListener<ApplicationReadyEvent> {

@Autowired
private MyService service;

  /**
   * This event is executed as late as conceivably possible to indicate that 
   * the application is ready to service requests.
   */
  @Override
  public void onApplicationEvent(final ApplicationReadyEvent event) {

    service.myMethod();

  }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM