1. Use of springboot cache
a.pom introduce jar spring-boot-starter-cache b.Add annotation to startup class@EnableCaching c.Add annotations to the methods that need to be cached @Cacheable(cacheNames = "com:xxx",key = "''+#id")
Figure 1
2. Implementation principle of cacheable
What is the implementation principle? The first reaction in my mind should of course be the famous concepts of AOP, dynamic agent and Interceptor. How can we verify them?
3. Implementation principle verification of cacheable
From the entry break point of calling the method getById to the CglibAopProxy dynamic proxy, you can see the key code to obtain the Interceptor call chain
# DynamicAdvisedInterceptor.intercept method List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
The specific Interceptor is shown in the figure below. Sure enough, there is a CacheInterceptor related to Cache. Since then, we have verified our guess in the second part
Figure 2
4. How is the principle realized?
a. Continue with the source code in step 3. Go inside to see where the Interceptor is obtained. Go down to see that the cached Interceptor is obtained through the advisor, as shown in Figure 3 below
b. Go on to locate the specific class beanfactory cacheoperationsourceadvisor, as shown in Figure 4 below
c. The latter logic is to obtain the configured Interceptor from the advisors. When we see the BeanFactory related operations, we must think of the related operations initialized when the application is started. Therefore, we should think of adding @ EnableCaching annotation to the startup class in step 1, so we go back to the starting position and track down.
d. We found an @ import ({cacheingconfigurationselector. Class}) annotation under @ enablecaching. We followed it to selectImports - > getProxyImports. In the getProxyImports method, we saw the following code Figure 5
e. Continue to the ProxyCachingConfiguration class and finally see whether the beanfactory cacheoperationsourceadvisor is associated with step 4? Is it associated with CacheInterceptor? Figure 6
5. How is the @ Cacheable annotation of the specific method associated with the CacheInterceptor?
Let's continue from Figure 4
# First step Located CacheOperationSourcePointcut.matches()method #Step two AbstractFallbackCacheOperationSource.getCacheOperations()method #Step 3: finally, the key is obtained from attributeCache public Collection<CacheOperation> getCacheOperations(Method method, @Nullable Class<?> targetClass) { ....Omit non critical code # Get key from cache Object cacheKey = this.getCacheKey(method, targetClass); Collection<CacheOperation> cached = (Collection)this.attributeCache.get(cacheKey); if (cached != null) { return cached != NULL_CACHING_ATTRIBUTE ? cached : null; } else { # If there is no key in the cache, judge whether the method has CacheOperation Collection<CacheOperation> cacheOps = this.computeCacheOperations(method, targetClass); if (cacheOps != null) { if (this.logger.isTraceEnabled()) { this.logger.trace("Adding cacheable method '" + method.getName() + "' with attribute: " + cacheOps); } # CacheOperation operation exists, put it into cache this.attributeCache.put(cacheKey, cacheOps); } else { # CacheOperation operation exists, which is stored in the empty collection this.attributeCache.put(cacheKey, NULL_CACHING_ATTRIBUTE); } return cacheOps; } }
Track this Computecacheoperations() method, locate parseCacheAnnotations() method, and finally see Cacheable, CacheEvict, CachePut and other related annotations. Since then, all the answers have been solved.
# SpringCacheAnnotationParser.parseCacheAnnotations() method Collection<CacheOperation> ops = new ArrayList(1); anns.stream().filter((ann) -> { return ann instanceof Cacheable; }).forEach((ann) -> { ops.add(this.parseCacheableAnnotation(ae, cachingConfig, (Cacheable)ann)); }); anns.stream().filter((ann) -> { return ann instanceof CacheEvict; }).forEach((ann) -> { ops.add(this.parseEvictAnnotation(ae, cachingConfig, (CacheEvict)ann)); }); anns.stream().filter((ann) -> { return ann instanceof CachePut; }).forEach((ann) -> { ops.add(this.parsePutAnnotation(ae, cachingConfig, (CachePut)ann)); }); anns.stream().filter((ann) -> { return ann instanceof Caching; }).forEach((ann) -> { this.parseCachingAnnotation(ae, cachingConfig, (Caching)ann, ops); }); return ops;
6. Summary
Previously, we combed the implementation principle of @ Cachebale under springboot from hypothesis to verification, and then summarized the major steps from top to bottom.
a.EnableCaching initializes the advisor and registers the interceptor interceptor
b. when the container is initialized, put the methods with Cache related annotations into attributeCache and Cache them
c. The method with Cache enhances the weaving interceptor through Cglib dynamic agent
d. locate the cacheinterceptor in combination with the initialization information of a and b to realize the functions of adding, deleting and changing the cache