自從spring3.1之后,spring引入了抽象緩存,可以通過在方法上添加@Cacheable等標簽對方法返回的數據進行緩存。但是它到底是怎么實現的呢,我們通過一個例子來看一下。首先我們定義一個@MyCacheable
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
package caching.springaop; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.annotation.ElementType; /** * 使用@MyCacheable注解方法 */ @Retention (RetentionPolicy.RUNTIME) @Target (ElementType.METHOD) public @interface MyCacheable{ } |
然后定義處理MyCacheable的切面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
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; /** * 處理MyCacheable方法的切面 */ @Aspect public class CacheAspect { private Logger logger = Logger.getLogger(CacheAspect. class ); private Map<String, Object> cache; public CacheAspect() { cache = new HashMap<String, Object>(); } /** * 所有標注了@Cacheable標簽的方法切入點 */ @Pointcut ( "execution(@MyCacheable * *.*(..))" ) @SuppressWarnings ( "unused" ) private void cache() { } @Around ( "cache()" ) public Object aroundCachedMethods(ProceedingJoinPoint thisJoinPoint) throws Throwable { logger.debug( "Execution of Cacheable method catched" ); //產生緩存數據的key值,像是這個樣子caching.aspectj.Calculator.sum(Integer=1;Integer=2;) StringBuilder keyBuff = new StringBuilder(); //增加類的名字 keyBuff.append(thisJoinPoint.getTarget().getClass().getName()); //加上方法的名字 keyBuff.append( "." ).append(thisJoinPoint.getSignature().getName()); keyBuff.append( "(" ); //循環出cacheable方法的參數 for ( final Object arg : thisJoinPoint.getArgs()) { //增加參數的類型和值 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; } } |
上述代碼展示了如何處理MyCacheable自定義的標簽,以及默認情況下產生key值的規則。最后生成的key值大概是這個樣子:caching.aspectj.Calculator.sum(Integer=1;Integer=2;)
下邊這段代碼在方法上添加了MyCacheable標簽
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
package caching.springaop; import org.apache.log4j.Logger; public class Calculator { private Logger logger = Logger.getLogger(Calculator. class ); @MyCacheable public int sum( int a, int b) { logger.info( "Calculating " + a + " + " + b); try { //假設這是代價非常高的計算 Thread.sleep( 3000 ); } catch (InterruptedException e) { logger.error( "Something went wrong..." , e); } return a + b; } } |
在方法上加了MyCacheable標簽,當key值相同的情況下會直接在緩存中獲取數據,如果沒有相同的key值,則會重新計算,因為這里只是一個加和操作,耗時非常的短暫。我們在這里讓其睡眠3秒鐘。
我們在spring-config.xml配置如下:
1
2
3
4
5
6
7
8
9
10
|
<? xml version = "1.0" encoding = "UTF-8" ?> < beans xmlns = "http://www.springframework.org/schema/beans" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns:aop = "http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> < aop:aspectj-autoproxy /> < bean class = "caching.springaop.CacheAspect" /> < bean id = "calc" class = "caching.springaop.Calculator" /> </ beans > |
測試類:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
package caching.springaop; import org.apache.log4j.Logger; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * 使用SpringAOP緩存的簡單例子 * @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 ClassPathXmlApplicationContext( "spring-config.xml" ); Calculator calc = (Calculator) ctx.getBean( "calc" ); //計算出來的結果將會被存儲在cache logger.info( "1 + 2 = " + calc.sum( 1 , 2 )); //從緩存中獲取結果 logger.info( "1 + 2 = " + calc.sum( 1 , 2 )); logger.debug( "Finished!" ); } } |
我們看一下運行的結果:
從結果來看第一次直接計算結果,第二次從緩存中獲取。
以上就是spring實現自定義緩存標簽的全部內容,希望對大家的學習有所幫助