Implementation of spring custom cache labels
Since spring3.1 and later, spring has introduced the abstract cache. You can add tags such as @ Cacheable to the method to cache the data returned by the method. But how is it implemented? Let's look at it through an example. First, we define a @ MyCacheable
Package caching. springaop; import java. lang. annotation. retention; import java. lang. annotation. retentionPolicy; import java. lang. annotation. target; import java. lang. annotation. elementType;/*** use @ MyCacheable annotation Method * @ author txxs */@ Retention (RetentionPolicy. RUNTIME) @ Target (ElementType. METHOD) public @ interface MyCacheable {}
Then define the Section for processing MyCacheable
Package caching. springaop; import java. util. hashMap; import java. util. map; import org. apache. log4j. logger; import org. aspectj. lang. proceedingJoinPoint; import org. aspectj. lang. annotation. around; import org. aspectj. lang. annotation. aspect; import org. aspectj. lang. annotation. pointcut;/*** process the section of the MyCacheable Method * @ author txxs */@ Aspectpublic class CacheAspect {private Logger logger = Logger. getLogger (CacheAspect. class); private Map
Cache; public CacheAspect () {cache = new HashMap
();}/*** All method entry points marked with the @ Cacheable tag */@ Pointcut (execution (@ MyCacheable **. *(..))) @ SuppressWarnings (unused) private void cache () {}@ Around (cache () public Object aroundCachedMethods (ProceedingJoinPoint thisJoinPoint) throws Throwable {logger. debug (Execution of Cacheable method catched); // the key value that generates the cached data, such as caching. aspectj. calculator. sum (Integer = 1; Integer = 2;) StringBuilder keyBuff = new StringBuilder (); // Add the class name keyBuff. append (thisJoinPoint. getTarget (). getClass (). getName (); // Add the method name keyBuff. append (.). append (thisJoinPoint. getSignature (). getName (); keyBuff. append (); // loop out the cacheable method parameter for (final Object arg: thisJoinPoint. getArgs () {// Add the parameter type and value keyBuff. append (arg. getClass (). getSimpleName () + = + arg +;);} keyBuff. append (); String key = keyBuff. toString (); logger. debug (Key = + key); Object result = cache. get (key); if (result = null) {logger. debug (Result not yet cached. must be calculated ...); result = thisJoinPoint. proceed (); logger.info (Storing calculated value '+ result +' to cache); cache. put (key, result);} else {logger. debug (Result '+ result + 'was found in cache); return result ;}}
The code above demonstrates how to deal with custom MyCacheable labels and rules for generating key values by default. The last generated key value is like this: caching. aspectj. Calculator. sum (Integer = 1; Integer = 2 ;)
The following code adds the MyCacheable label to the method.
Package caching. springaop; import org. apache. log4j. logger;/*** time calculation class * @ author Igor Urmincek * @ author txxs */public class Calculator {private Logger logger = Logger. getLogger (Calculator. class); @ MyCacheablepublic int sum (int a, int B) {logger.info (Calculating + a ++ B); try {// assume this is a very costly computing Thread. sleep (3000);} catch (InterruptedException e) {logger. error (Something went wrong ..., e);} return a + B ;}}
The MyCacheable label is added to the method. If the key value is the same, the data is directly obtained in the cache. If the key value is not the same, the calculation is performed again, this is just a addition operation, which takes a short time. Let's sleep for 3 seconds here.
The configuration in the spring-config.xml is as follows:
<!--{cke_protected}{C}%3C!%2D%2D%3Fxml%20version%3D1.0%20encoding%3DUTF-8%3F%2D%2D%3E--><beans aop="" beans="" http:="" schema="" spring-aop-2.5.xsd="" spring-beans-2.5.xsd="" www.springframework.org="" xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://www.springframework.org/schema/aop"><aop:aspectj-autoproxy><bean class="caching.springaop.CacheAspect"><bean class="caching.springaop.Calculator" id="calc"></bean></bean></aop:aspectj-autoproxy></beans>
Test class:
Package caching. springaop; import org. apache. log4j. logger; import org. springframework. context. applicationContext; import org. springframework. context. support. classPathXmlApplicationContext;/*** simple example of using Spring AOP cache * @ author txxs */public class App {private static Logger logger = Logger. getLogger (App. class); public static void main (String [] args) {logger. debug (Starting ...); applicationContext ctx = new Cl AssPathXmlApplicationContext (spring-config.xml); Calculator calc = (Calculator) ctx. getBean (calc); // The calculated results will be stored in cachelogger.info (1 + 2 = + calc. sum (1, 2); // obtain the result logger.info (1 + 2 = + calc. sum (1, 2); logger. debug (Finished !);}}
Let's take a look at the running results:
10:43:26, 953 [main] DEBUG caching. springaop. CacheAspect. aroundCachedMethods (CacheAspect. java: 37)-Execution of Cacheable method catched
10:43:26, 954 [main] DEBUG caching. springaop. cacheAspect. aroundCachedMethods (CacheAspect. java: 52)-Key = caching. springaop. calculator. sum (Integer = 1; Integer = 2 ;)
10:43:26, 955 [main] DEBUG caching. springaop. CacheAspect. aroundCachedMethods (CacheAspect. java: 55)-Result not yet cached. Must be calculated...
10:43:26, 978 [main] INFO caching. springaop. Calculator. sum (Calculator. java: 14)-Calculating 1 + 2
10:43:29, 979 [main] INFO caching. springaop. CacheAspect. aroundCachedMethods (CacheAspect. java: 57)-Storing calculated value '3' to cache
10:43:29, 979 [main] INFO caching. springaop. App. main (App. java: 20)-1 + 2 = 3
10:43:29, 979 [main] DEBUG caching. springaop. CacheAspect. aroundCachedMethods (CacheAspect. java: 37)-Execution of Cacheable method catched
10:43:29, 979 [main] DEBUG caching. springaop. cacheAspect. aroundCachedMethods (CacheAspect. java: 52)-Key = caching. springaop. calculator. sum (Integer = 1; Integer = 2 ;)
10:43:29, 979 [main] DEBUG caching. springaop. CacheAspect. aroundCachedMethods (CacheAspect. java: 60)-Result '3' was found in cache
10:43:29, 980 [main] INFO caching. springaop. App. main (App. java: 22)-1 + 2 = 3
10:43:29, 980 [main] DEBUG caching. springaop. App. main (App. java: 23)-Finished!