@启动期间可缓存和初始化



我想在启动春季启动应用程序(从DB加载内容(期间初始化缓存中的所有条目。理想情况下,这是在应用程序准备就绪之前完成的。所以我在@PostConstruct中实现了所有加载。我注意到,缓存尚未在@PostContruct中设置,我遵循了一些技巧在ApplicationReadyEvent中进行此类初始化。然而,这仍然没有如预期的那样起作用:

尽管我已经在ApplicationReadyEvent中调用了@Cacheable方法,但第二次调用重新进入该方法,而不是使用缓存。

我的服务:

@Service
public class MyService implements ApplicationListener<ApplicationReadyEvent {
@Cacheable("entry")
public List<String> getEntry() {
System.out.println("getEntry called!");
return Arrays.asList("aaa", "bbb");
}
@Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
System.out.println("*** onApplicationEvent");
getEntry();
}
}

我的咖啡因缓存管理器配置:

@Configuration
@EnableCaching
public class CachingConfig {
@Bean
public CacheManager cacheManager() {
List<CaffeineCache> caffeineCaches = chacheList(Arrays.asList(
"entry"
));
SimpleCacheManager simpleCacheManager = new SimpleCacheManager();
simpleCacheManager.setCaches(caffeineCaches);
System.out.println("*** @Bean CacheManager");
return simpleCacheManager;
}
private List<CaffeineCache> chacheList(List<String> cacheNames) {
return cacheNames.stream().map(s -> new CaffeineCache(s, Caffeine.newBuilder().build()))
.collect(Collectors.toList());
}
}

使用服务的简单REST端点:

@RestController
public class MyController {
@Autowired
MyService myService;
@GetMapping("/test")
public void test()
{
System.out.println("*** GET /test");
myService.getEntry();
}
}

如果我启动应用程序并执行两个GET /test,我会得到以下输出:

INFO 20120  --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 907 ms
*** @Bean CacheManager
INFO 20120  --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
INFO 20120  --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
INFO 20120  --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 1.639 seconds (JVM running for 2.473)
*** onApplicationEvent
*** getEntry called!
INFO 20120  --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
INFO 20120  --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
INFO 20120  --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 4 ms
*** GET /test
*** getEntry called!
*** GET /test

那么为什么MyService.getEntry的第二次调用(即"启动"后的第一次调用(会再次进入代码?

最后,我需要一个解决方案,它在应用程序完成启动之前执行第一次加载,即我将尝试ContextRefreshedEvent或再次尝试@PostConstruct(以及@Autowire CacheManager,以便在执行@PostConstruct之前对其进行配置(。但第一步是让这个例子按预期运行。

好的,愚蠢的错误:在我的服务中,对getEntry()的调用必须通过代理对象完成,而不是直接调用:

@Service
public class MyService implements ApplicationListener<ApplicationReadyEvent {
@Autowired
MyService self;
@Cacheable("entry")
public List<String> getEntry() {
System.out.println("getEntry called!");
return Arrays.asList("aaa", "bbb");
}
@Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
System.out.println("*** onApplicationEvent");
self.getEntry();
}
}

最新更新