springboot cache @ EnableCaching instance

  • 2021-12-11 07:21:33
  • OfStack

How Directory springboot Cache @ EnableCachingSpring @ EnableCaching Works

springboot Cache @ EnableCaching

Most of the time, the bottleneck of the system lies in 1 more complex IO operation, such as reading the database. If 1 more stable data, 1 general solution is to use cache. spring boot provides a relatively simple caching scheme. Simple caching can be accomplished by using @ EnableCaching.

There are many implementations of cache, such as ConcurentHashMapCache, GuavaCache, EnCacheCache, etc. spring and boot have default implementations. This article does not go deep into the source code interpretation, first of all, use it.

Here we simulate the User to be cached


class User {
 private Long id;
 private String name;
// setter getter
}

Then our business object:


import javax.annotation.PostConstruct;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.stereotype.Component;
/**
 * @author micro
 * @date 2017 Year 8 Month 2 Day 
 * @description :
 */
@Component
@EnableCaching
public class UserDao {
 private Map<Long, User> userMap;
 @PostConstruct
 public void init() {
  // Analog database 
  userMap = new HashMap<Long, User>();
  userMap.put(1L, new User(1L,"micro1"));
  userMap.put(2L, new User(2L, "micro2"));
 }
 
 @Cacheable("user")  //  Annotation key Property can execute the cache object user( It can be understood as 1 A map) Adj. key 
 public User getUser(Long userId) {
  System.out.println(" Query database :userId ->" + userId);
  return userMap.get(userId);
 }
 
 @Cacheable(value = "nameCache", key = "#name")
 public User getUserByName(Long userId, String name) {
  System.out.println(" Query database :userId ->" + userId);
  return userMap.get(userId);
 }
 
 @Cacheable("nameCache")
 public User getUserByName(String name) {
  System.out.println(" Query database :userName : " + name);
  for (Long k : userMap.keySet()) {
   if (userMap.get(k).equals(name)) {
    return userMap.get(k);
   }
  }
  return null;
 }
 
 @CachePut("user") //  And Cacheable The difference is Cacheable Look at the cache first. If there is, directly cache and swap it back. CachePut It is called every time and the return value is put in the cache 
 public User getUser2(Long userId) {
  System.out.println(" Query database :userId : " + userId);
  return userMap.get(userId);
 }
 
 @CacheEvict("user")
 public void removeFromCache(Long userId) {
  return ;
 }
}

Then we write the startup class:


@SpringBootApplication
public class CacheTest implements CommandLineRunner {
 @Autowired
 private UserDao userDao; 
 public static void main(String[] args) {
  new SpringApplication(CacheTest.class).run(args);
 } 
 @Override
 public void run(String... args) throws Exception {
  System.out.println(" No. 1 1 Secondary query ");
  System.out.println(userDao.getUser(1L));
  System.out.println(" No. 1 2 Secondary query ");
  System.out.println(userDao.getUser(1L));
  userDao.removeFromCache(1L);//  Remove cache 
  System.out.println(" No. 1 3 Secondary query ");
  userDao.getUser(1L);//  There is no cache   
  System.out.println("--------");
  //  Test different key Cache 
  userDao.getUserByName("micro1");
  userDao.getUserByName(1L, "micro1");//  Parameters specified name  For key  This read cache 
 }
}

Print results:

First inquiry
Query database: userId- > 1
User@65da01f4
Second inquiry
User@65da01f4
Third inquiry
Query database: userId- > 1
--------
Query database: userName: micro1

Working principle of Spring @ EnableCaching

1. Developers use annotation @ EnableCaching

2. Note @ EnableCaching Import CachingConfigurationSelector

3. CachingConfigurationSelector decides which configuration classes to introduce according to the annotation @ EnableCaching attribute AdviceMode mode

PROXY : AutoProxyRegistrar, ProxyCachingConfiguration; ASPECTJ AspectJCachingConfiguration;

This paper takes mode=PROXY as an example.

4. Importing CachingConfigurationSelector into AutoProxyRegistrar will ensure that there is an automatic proxy creator (APC) in the container;

Used to ensure that a proxy creator is available when the target bean needs to be proxy

5. ProxyCachingConfiguration defines the following infrastructure to the container bean

bean with name org. springframework. cache. config. internalCacheAdvisor of Type BeanFactoryCacheOperationSourceAdvisor bean with name cacheOperationSource and type CacheOperationSource

Metadata used to get the Spring Cache annotation that is finally applied when the method is called

bean with name cacheInterceptor and type CacheInterceptor

1 MethodInterceptor, AOP Advice wrapped around the target bean for operating Cache.

6. AutoProxyRegistrar processes the creation of each bean in the container startup stage, and if there is a method in the bean that applies Spring Cache annotation, creates a corresponding proxy object for it, and wraps the BeanFactoryCacheOperationSourceAdvisor bean defined above;

7. The bean method with Spring Cache annotation is called. In fact, the call first occurs on the proxy object, first reaches cacheInterceptor, and then is the call of the target bean method;

cacheInterceptor handles both pre-call caching and on-call caching

Related articles: