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

时间:2017-01-17 14:17:47

标签: java spring caching spring-cache

我使用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");
    }
}

3 个答案:

答案 0 :(得分:0)

尝试使用ApplicationStartedEvent代替@PostConstruct注释。

我遇到了同样的问题,这个小小的改动解决了它。

您应该添加 @EventListener(classes = ApplicationStartedEvent.class) 在您的方法和传递之上 ApplicationStartedEvent event 作为参数。

示例:

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

答案 1 :(得分:-1)

@PostConstruct将适用于您的情况。在实例化方法bean之后,将调用带有@PostConstruct注释的方法。

但是如果依赖于其他bean,那么在应用程序上下文完全启动后你会调用你的方法吗?你可以像这样创建一个新的bean:

websocket.onmessage = function (event) {
    document.getElementById("foto").src = "data:image/png;event.data)";
};

答案 2 :(得分:-1)

使用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();

  }

}