Я пытаюсь инициализировать свой кеш данными при запуске приложения, но это не работает. Мой код:
springBootApplication
package com.r2b.springcache;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan("com.r2b")
@SpringBootApplication
@EnableCaching
public class SpringCacheApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCacheApplication.class, args);
}
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager("student");
}
}
ученик
package com.r2b.model;
public class Student {
String id;
String name;
String clz;
public Student(String id, String name, String clz) {
super();
this.id = id;
this.name = name;
this.clz = clz;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClz() {
return clz;
}
public void setClz(String clz) {
this.clz = clz;
}
//Setters and getters
}
studentService
package com.r2b.service;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import com.r2b.model.Student;
@Service
public class StudentService
{
@Cacheable("student")
public Student getStudentByID(String id)
{
try
{
System.out.println("Going to sleep for 5 Secs.. to simulate backend call.");
Thread.sleep(1000*5);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
return new Student(id,"Sajal" ,"V");
}
}
StudentController
package com.r2b.controller;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import com.r2b.model.Student;
import com.r2b.service.StudentService;
@RestController
public class StudentController
{
@Autowired
StudentService studentService;
@PostConstruct
public void init() {
studentService.getStudentByID("1");
}
@GetMapping("/student/{id}")
public Student findStudentById(@PathVariable String id)
{
System.out.println("Searching by ID : " + id);
return studentService.getStudentByID(id);
}
}
pom.xml
<?xml version = "1.0" encoding = "UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.r2b</groupId>
<artifactId>spring-cache</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-cache</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
когда я перехожу к http: // локальный: 8080 / студент / 1 в первый раз, кеш не активен, и ответ занимает более 5 секунд, но когда я обновляюсь, кеш отвечает, и запрос занимает несколько миллисекунд! несмотря на то, что я вызвал метод кеширования в postConstruct, я попытался использовать @AfterPropertiesSet, и он тоже не работает!
Любая идея ?
Спасибо
Ваш метод init() действительно выполняется?
Да, выполняется при запуске весны




Это не работает, потому что прокси еще не инициализирован. На самом деле это задокументировано в руководстве пользователя
In proxy mode (the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation (in effect, a method within the target object that calls another method of the target object) does not lead to actual caching at runtime even if the invoked method is marked with @Cacheable. Consider using the aspectj mode in this case. Also, the proxy must be fully initialized to provide the expected behavior, so you should not rely on this feature in your initialization code (that is, @PostConstruct).
Это именно то, что вы здесь делаете. Кеширование должно быть максимально прозрачным, поэтому предварительная загрузка кеша при запуске кажется мне немного странной (и увеличивает время запуска).
Можете ли вы опубликовать пример конфигурации aspectj, если это возможно?
если я устанавливаю метод, который я запускаю в асинхронном режиме через 1 минуту после загрузки контекстной пружины, разве это не чище, чем использование аспектаj?
Ответ прост, но мне потребовалось почти день, чтобы понять, что методы, украшенные @Cacheable, не действуют в @PostConstruct.
Просто замените ваш @PostConstruct на @EventListener (ApplicationReadyEvent.class)
@EventListener(ApplicationReadyEvent.class)
public void init() {
studentService.getStudentByID("1");
}
NB. Если исключение генерируется из метода, украшенного событием @PostConstruct или EventListener (ApplicationReadyEvent.class), ваше приложение завершит работу ...
Название должно быть на английском языке.