The implementation principle of @Cacheable

Source: Internet
Author: User
Tags aop

If you have used spring Cache, you must be familiar with this configuration and code:

<cache:annotation-driven cache-manager="cacheManager"proxy-target-class="true" order="1"/>
@Cacheable(value = "3600", key = "i‘m a cache key")publicList<Object> getData(){}

The above two pieces of code, XML is to enable the cache annotation annotations and register a CacheManager, the second code in GetData will go to the cache first, if the cache does not execute GetData the true logic.

So today's "go to Science" is about how spring does the automatic caching of method levels with just a single XML configuration and one annotation.

The best part of our spring is that the IOC container for the bean management, can be said to be the cornerstone of spring, then the drawing of the wind, to the beginning of our discussion today is the spring at the start of the various tags in the XML parsing, such as the corresponding <cache: Annotation-driven> tags, is responsible for parsing is the Annotationdrivencachebeandefinitionparser.parse method, the code looks very simple, according to the mode attribute registered Advisor Component:

Expand the original code

We look at the default Mode=proxy today, enter the method, found that the method registered three beans into the context, respectively, is Cacheoperationsource, Cacheinterceptor and Beanfactorycacheoperationsourceadvisor.

Familiar with the principles of AOP see Interceptor and advisor will generally understand the majority, and they have a common attribute cacheoperationsources, The implementation class is Org.springframework.cache.annotation.AnnotationCacheOperationSource.

Here we first meow two eyes these two classes, first see beanfactorycacheoperationsourceadvisor, inside there is a called Cacheoperationsourcepointcut pointcut, Used to match whether the method needs to go to the interceptor. Get cacheoperation by calling the cacheoperationsources.getcacheoperations that you injected before, the code is as follows:

Expand the original code

This will only be blocked by the Cacheoperationsourcepointcut matching method and cached by Attributecache.

Then look at the Cacheinterceptor class, first see the Inheritance structure:

This class is simple, just rewriting the methodinterceptor Invoke method:

Expand the original code

The next step is to call Cacheaspectsupport

protectedObject execute(CacheOperationInvoker invoker, Object target, Method method, Object[] args) {   // check whether aspect is enabled   // to cope with cases where the AJ is pulled in automatically   if(this.initialized) {      Class<?> targetClass = getTargetClass(target);      Collection<CacheOperation> operations = getCacheOperationSource().getCacheOperations(method, targetClass);      if(!CollectionUtils.isEmpty(operations)) {         returnexecute(invoker, newCacheOperationContexts(operations, method, args, target, targetClass));      }   }   returninvoker.invoke();}

Where execute is called after obtaining cacheoperations according to Getcacheoperations is the key, Where Getcacheoperationsource is the cacheoperationsources in the bean that was said before, That is Org.springframework.cache.annotation.AnnotationCacheOperationSource, which is responsible for three tag calls: @Cacheable, @ Cacheput and @cacheevict.

Here's a look at the code for the Execute method:

privateObject execute(CacheOperationInvoker invoker, CacheOperationContexts contexts) {   // Process any early evictions   processCacheEvicts(contexts.get(CacheEvictOperation.class), true, ExpressionEvaluator.NO_RESULT);   // Check if we have a cached item matching the conditions   Cache.ValueWrapper cacheHit = findCachedItem(contexts.get(CacheableOperation.class));   // Collect puts from any @Cacheable miss, if no cached item is found   List<CachePutRequest> cachePutRequests = new LinkedList<CachePutRequest>();   if(cacheHit == null) {      collectPutRequests(contexts.get(CacheableOperation.class), ExpressionEvaluator.NO_RESULT, cachePutRequests);   }   Cache.ValueWrapper result = null;   // If there are no put requests, just use the cache hit   if(cachePutRequests.isEmpty() && !hasCachePut(contexts)) {      result = cacheHit;   }   // Invoke the method if don‘t have a cache hit   if(result == null) {      result = newSimpleValueWrapper(invokeOperation(invoker));   }   // Collect any explicit @CachePuts   collectPutRequests(contexts.get(CachePutOperation.class), result.get(), cachePutRequests);   // Process any collected put requests, either from @CachePut or a @Cacheable miss   for(CachePutRequest cachePutRequest : cachePutRequests) {      cachePutRequest.apply(result.get());   }    // Process any late evictions   processCacheEvicts(contexts.get(CacheEvictOperation.class), false, result.get());   returnresult.get();}

This code seems to be relatively "simple", but also the core implementation of the spring cache logic, according to the annotations performed before and after the method of the cache operation, note that the invalid operation is divided into early evictions and late evictions, Corresponds to the Beforeinvocation attribute in the label @cacheevict. Since then, the logic for Spring cache has been executed.

There are two more points to note.

    1. The above implementation is implemented by proxy, then the method of the object is an internal call (that is, this reference) instead of an external reference, it will cause the proxy to fail, that is, the annotation invalidation.
    2. Non-public method ibid.
    3. The @CacheEvict tag does not empty the cache of the method that throws the exception by setting Beforeinvocation to True, that is, before the method executes

Last words:

This article does not speak about the principles of spring's AOP implementation and the details of the spring cache.

Reference:

Https://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html

https://www.ibm.com/developerworks/cn/opensource/os-cn-spring-cache/

Http://www.cnblogs.com/chanedi/p/4552555.html

Originally published on October 16, 2015

The implementation principle of @Cacheable

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.