【问题标题】:Spring cache using @Cacheable not working on startup @PostConstruct使用@Cacheable 的Spring 缓存在启动@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)。最好在侦听ContextRefreshedEvents 的ApplicationListener 中执行此类操作。那就是告诉你一切都已经开始的触发器,你现在可以调用缓存方法了。
  • @M.Deinum 好的,但我需要在启动 REST 端点并侦听请求之前启动缓存。我该怎么做?
  • 一旦 dispatcherservlet 启动,它就会在监听...如前所述,使用ApplicationListener 以确保安全。
  • @M.Deinum 谢谢,这解决了我的问题!

标签: java spring caching spring-cache


【解决方案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
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-04-05
      • 2018-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-02
      • 2019-05-02
      • 1970-01-01
      相关资源
      最近更新 更多