spring與redis集成之aop整合方案

 

java使用redis緩存能夠使用jedis框架,jedis操做簡單,沒有什麼複雜的東西須要學習,網上資料不少,隨便看看就會了.html

將spring與redis緩存集成,其實也是使用jedis框架,只不過spring對它進行了一層封裝,並將這層封裝庫命名爲spring-data-redis.java

下面將要使用spring-data-redis與jedis的jar包,並經過spring的aop功能,將redis緩存無縫無侵入的整合進來.redis

1.先下載好依賴包spring

 

[html]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. <dependency>  
  2.     <groupId>org.springframework</groupId>  
  3.     <artifactId>spring-core</artifactId>  
  4.     <version>4.1.1.RELEASE</version>  
  5. </dependency>  
  6. <!-- 還有spring的其它包,這裏不一一貼出-->  

 

 

[html]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. <dependency>    
  2.     <groupId>org.springframework.data</groupId>    
  3.     <artifactId>spring-data-redis</artifactId>    
  4.     <version>1.4.1.RELEASE</version>    
  5. </dependency>   
  6. <dependency>   
  7.     <groupId>redis.clients</groupId>   
  8.     <artifactId>jedis</artifactId>   
  9.     <version>2.6.0</version>   
  10. </dependency>   


2.再配置spring文件後端

 

 

[html]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1.    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">  
  2.     <property name="minIdle" value="${redis.minIdle}" />  
  3.        <property name="maxIdle" value="${redis.maxIdle}" />    
  4.        <property name="maxTotal" value="${redis.maxActive}" />    
  5.        <property name="maxWaitMillis" value="${redis.maxWait}" />    
  6.        <property name="testOnBorrow" value="${redis.testOnBorrow}" />    
  7.    </bean>    
  8.      
  9.    <bean id="jedisConnFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">  
  10.        <property name="hostName" value="${redis.host}" />  
  11.        <property name="port" value="${redis.port}" />  
  12.        <property name="password" value="${redis.password}" />  
  13.        <property name="usePool" value="true" />  
  14.        <property name="poolConfig" ref="poolConfig" />  
  15.    </bean>   
  16.      
  17. <!-- redis template definition -->  
  18. <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">  
  19.     <property name="connectionFactory" ref="jedisConnFactory" />  
  20.     <property name="keySerializer">  
  21.         <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />  
  22.     </property>     
  23.     <property name="valueSerializer">  
  24.         <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />  
  25.     </property>  
  26.     <property name="hashKeySerializer">    
  27.        <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>    
  28.     </property>  
  29.     <property name="hashValueSerializer">  
  30.        <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>    
  31.     </property>  
  32. </bean>  


3.開始編寫aop代碼緩存

 

3.1 聲明兩個註解類,用於定義哪些方法將使用緩存app

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. @Retention(RetentionPolicy.RUNTIME)  
  2. @Target({ElementType.METHOD})  
  3. public @interface Cacheable {  
  4.       
  5.     public enum KeyMode{  
  6.         DEFAULT,    //只有加了@CacheKey的參數,才加入key後綴中  
  7.         BASIC,      //只有基本類型參數,才加入key後綴中,如:String,Integer,Long,Short,Boolean  
  8.         ALL;        //全部參數都加入key後綴  
  9.     }  
  10.       
  11.     public String key() default "";     //緩存key  
  12.     public KeyMode keyMode() default KeyMode.DEFAULT;       //key的後綴模式  
  13.     public int expire() default 0;      //緩存多少秒,默認無限期  
  14. }  

 

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. @Retention(RetentionPolicy.RUNTIME)  
  2. @Target({ElementType.PARAMETER})  
  3. public @interface CacheKey {}  

3.2 建立一個Aop攔截器的處理類,用於攔截加了@Cacheable的方法框架

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. @Aspect  
  2. @Component  
  3. public class CacheableAop {  
  4.       
  5.     @Autowired private RedisTemplate redisTemplate;  
  6.       
  7.     @Around("@annotation(cache)")  
  8.     public Object cached(final ProceedingJoinPoint pjp,Cacheable cache) throws Throwable {  
  9.           
  10.         String key=getCacheKey(pjp, cache);  
  11.         ValueOperations<String, Object> valueOper=redisTemplate.opsForValue();  
  12.         Object value=valueOper.get(key);    //從緩存獲取數據  
  13.         if(value!=null) return value;       //若是有數據,則直接返回  
  14.           
  15.         value = pjp.proceed();      //跳過緩存,到後端查詢數據  
  16.         if(cache.expire()<=0) {      //若是沒有設置過時時間,則無限期緩存  
  17.             valueOper.set(key, value);  
  18.         } else {                    //不然設置緩存時間  
  19.             valueOper.set(key, value,cache.expire(),TimeUnit.SECONDS);  
  20.         }  
  21.         return value;  
  22.     }  
  23.       
  24.     /** 
  25.      * 獲取緩存的key值 
  26.      * @param pjp 
  27.      * @param cache 
  28.      * @return 
  29.      */  
  30.     private String getCacheKey(ProceedingJoinPoint pjp,Cacheable cache) {  
  31.           
  32.         StringBuilder buf=new StringBuilder();  
  33.         buf.append(pjp.getSignature().getDeclaringTypeName()).append(".").append(pjp.getSignature().getName());  
  34.         if(cache.key().length()>0) {  
  35.             buf.append(".").append(cache.key());  
  36.         }  
  37.           
  38.         Object[] args=pjp.getArgs();  
  39.         if(cache.keyMode()==KeyMode.DEFAULT) {  
  40.             Annotation[][] pas=((MethodSignature)pjp.getSignature()).getMethod().getParameterAnnotations();  
  41.             for(int i=0;i<pas.length;i++) {  
  42.                 for(Annotation an:pas[i]) {  
  43.                     if(an instanceof CacheKey) {  
  44.                         buf.append(".").append(args[i].toString());  
  45.                         break;  
  46.                     }  
  47.                 }  
  48.             }  
  49.         } else if(cache.keyMode()==KeyMode.BASIC) {  
  50.             for(Object arg:args) {  
  51.                 if(arg instanceof String) {  
  52.                     buf.append(".").append(arg);  
  53.                 } else if(arg instanceof Integer || arg instanceof Long || arg instanceof Short) {  
  54.                     buf.append(".").append(arg.toString());  
  55.                 } else if(arg instanceof Boolean) {  
  56.                     buf.append(".").append(arg.toString());  
  57.                 }  
  58.             }  
  59.         } else if(cache.keyMode()==KeyMode.ALL) {  
  60.             for(Object arg:args) {  
  61.                 buf.append(".").append(arg.toString());  
  62.             }  
  63.         }  
  64.           
  65.         return buf.toString();  
  66.     }  
  67. }  

4.使用緩存示例學習

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. @Service  
  2. @Transactional  
  3. public class DemoServiceImpl implements DemoService {  
  4.   
  5.     @Autowired private DemoDao demoDao;  
  6.   
  7.     public List<Demo> findAll() {  
  8.         return demoDao.findAll();  
  9.     }  
  10.       
  11.     /* 
  12.         對get()方法配置使用緩存,緩存有效期爲3600秒,緩存的key格式爲:{package_name}.DemoServiceImpl.get 
  13.         同時爲參數配置了@CacheKey後,表示此參數的值將作爲key的後綴,此例的key,最終是:{package_name}.DemoServiceImpl.get.{id} 
  14.         能夠爲多個參數配置@CacheKey,攔截器會調用參數的toString()作爲key的後綴 
  15.         若配置多個@CacheKey參數,那麼最終的key格式爲:{package_name}.{class_name}.{method}.{arg1}.{arg2}.{...} 
  16.      */  
  17.     @Cacheable(expire=3600)  
  18.     public Demo get(@CacheKey String id) {  
  19.         return demoDao.get(id);  
  20.     }  
  21.   
  22.     public Demo getByName(String name) {  
  23.         return demoDao.getByName(name);  
  24.     }  
  25. }  

 

    • 若爲名稱相同的方法配置緩存,能夠在@Cacheable中加入key屬性,追加額外的key後綴
    • @Cacheable還有一個KeyMode屬性,用於配置哪些參數能夠追加到key後綴中,默認取值 DEFAULT:表示只有加了@CacheKey的參數才能追加到key後綴BASIC:自動將基本類型追加到key後綴,而無需再配置@CacheKeyALL:自動將全部參數追加到lkey後綴,而無需再配置@CacheKey
相關文章
相關標籤/搜索