如何在春季启动时加载@Cache?

mem*_*und 14 java spring spring-cache

我正在使用spring-cache来改进数据库查询,其工作正常如下:

@Bean
public CacheManager cacheManager() {
    return new ConcurrentMapCacheManager("books");
}

@Cacheable("books")
public Book getByIsbn(String isbn) {
    return dao.findByIsbn(isbn);
}
Run Code Online (Sandbox Code Playgroud)

但现在我想在启动时预先填充完整的书籍缓存.这意味着我想调用dao.findAll()并将所有值放入缓存中.此例程不应仅定期安排.

但是如何在使用时显式填充缓存@Cacheable

Lok*_*oki 14

只需像以前一样使用缓存,添加一个调度程序来更新缓存,下面是代码片段.

@Service
public class CacheScheduler {
    @Autowired
    BookDao bookDao;
    @Autowired
    CacheManager cacheManager;

    @PostConstruct
    public void init() {
        update();
        scheduleUpdateAsync();
    }

    public void update() {
        for (Book book : bookDao.findAll()) {
            cacheManager.getCache("books").put(book.getIsbn(), book);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

确保您KeyGenerator将返回一个参数的对象(默认情况下).或者,将putToCache方法公开BookService以避免直接使用cacheManager.

@CachePut(value = "books", key = "#book.isbn")
public Book putToCache(Book book) {
    return book;
}
Run Code Online (Sandbox Code Playgroud)


小智 7

使用@PostConstruct时,我遇到了以下问题:-即使调用了我想缓存的方法,从招摇动的方法调用后,它仍然没有使用缓存的值。只有在再次调用它之后。

那是因为@PostConstruct缓存某些内容还为时过早。(至少我认为这是问题所在)

现在,我在启动过程中使用的时间更晚,并且可以正常使用:

@Component
public class CacheInit implements ApplicationListener<ApplicationReadyEvent> {

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
       //call service method
    }

}
Run Code Online (Sandbox Code Playgroud)


mla*_*dzo 5

一个选项是使用CommandLineRunner在启动时填充缓存。

从官方 CommandLineRunner 文档来看,它是:

用于指示 bean包含在SpringApplication中时应该运行的接口。

因此,我们只需要检索所有可用书籍的列表,然后使用CacheManager填充书籍缓存。

@Component
public class ApplicationRunner implements CommandLineRunner {
    @Autowired
    private BookDao dao;

    @Autowired
    private CacheManager cacheManager;

    @Bean
    public CacheManager cacheManager() {
        return new ConcurrentMapCacheManager("books");
    }

    @Override
    public void run(String... args) throws Exception {

        List<Book> results = dao.findAll();

        results.forEach(book -> 
            cacheManager.getCache("books").put(book.getId(), book));
    }
}
Run Code Online (Sandbox Code Playgroud)