Home > Mobile >  Cacheable Annotation in Spring Boot
Cacheable Annotation in Spring Boot

Time:06-13

Service Class

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class StudentService{
   
    @Cacheable(value = "student",key = "{#id,#name}")
    public Student getStudentByID(String id,String name)
    {
        return new Student(id,name ,"V");
    }
} 

ThreadExample Class

 public class ThreadExample extends   Thread{

    @Autowired
    StudentService studentService;

    @Override
    public void run() {
        studentService.getStudentByID("3","f");
    }
}

I have both class and start the threads as :


  for (int i = 0; i < 24; i  ) {
      new ThreadExample().start();
  }

The problem is cacheable annotation does not work here , because it is not a spring bean class. But the things I try to do just execute one time getStudentByID(String id,String name) function with same id and name. How I can do that ? Do you have any idea. Thank you

CodePudding user response:

StudentService in ThreadExample class would be null because;

Spring only autowires components the components it creates. You are calling new ThreadExample(), Spring doesn't know about this object so no auto-wiring will take place. See https://stackoverflow.com/a/42502608/2039546

There may be 2 different methods for this, depending on your use case;

  • The first and fastest option is to send the service to the ThreadExample class with the constructor. You can do this easily.

  • Other option when you create ThreadExample ask app context to do your auto-wiring. Let me give an example of this.

The pseudocode will be something like this;

@Controller
public class TestController {

    private final ApplicationContext applicationContext;

    public TestController(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @GetMapping(value = "/test")
    public void test() {
        ThreadExample threadExample = new ThreadExample();
        applicationContext.getAutowireCapableBeanFactory()
                .autowireBean(threadExample);
        for (int i = 0; i < 24; i  ) {
            Thread thread = new Thread(threadExample);
            thread.start();
        }
    }
}
public class ThreadExample implements Runnable {

    @Autowired
    private StudentService studentService;

    @Override
    public void run() {
        long threadId = Thread.currentThread().getId();
        String threadName = Thread.currentThread().getName();
        System.out.println(String
                .format("Thread has been called! [threadId=%s, threadName=%s]",
                        threadId, threadName));
        Student student = studentService.getStudentByID("3", "f");
        System.out.println(String
                .format("Thread has been completed. [threadId=%s, threadName=%s, studentId=%s]",
                        threadId, threadName, student.getId()));
    }
}
@Service
public class StudentService {

    @Cacheable(value = "students", key = "{#id, #name}", sync = true)
    public Student getStudentByID(String id, String name) {
        System.out.println(String
                .format("getStudentById() has been called! [id=%s, name=%s]", id, name));
        return new Student(id, name , "V");
    }
}

Notice the sync = true attribute which tells the framework to block any concurrent threads while the value is being computed. This will make sure that this intensive operation is invoked only once in case of concurrent access.

The console output is:

Thread has been called! [threadId=40, threadName=Thread-7]
Thread has been called! [threadId=41, threadName=Thread-8]
Thread has been called! [threadId=42, threadName=Thread-9]
Thread has been called! [threadId=43, threadName=Thread-10]

.
.
.
getStudentById() has been called! [id=3, name=f] <- ONLY WORKED ONCE!
Thread has been completed. [threadId=54, threadName=Thread-21, studentId=3]
Thread has been completed. [threadId=55, threadName=Thread-22, studentId=3]
Thread has been completed. [threadId=57, threadName=Thread-24, studentId=3]
Thread has been completed. [threadId=47, threadName=Thread-14, studentId=3]
Thread has been completed. [threadId=42, threadName=Thread-9, studentId=3]
.
.
.
  • Related