于吉吉的技術(shù)博客

          建造高性能門戶網(wǎng)

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            65 隨筆 :: 6 文章 :: 149 評論 :: 0 Trackbacks
          由于系統(tǒng)需求需 要對各個(gè)接口進(jìn)行key-value緩存(以參數(shù)為key,返回的對象為value),當(dāng)然對于這種情況首先考慮到的是使用aop,前段時(shí)間看過 aspectj的一些介紹,借此機(jī)會正好加以應(yīng)用和體會一下,aspectj是AOP最早成熟的java實(shí)現(xiàn),它稍微擴(kuò)展了一下java語言,增加了一些 keyword等,具體的aspectj的基本語法見[ur=http://today.java.net/pub/a/today/2003/12 /26/ch3AspectJSyntaxBasics.html]這里[/url],進(jìn)行緩存的框架使用較成熟的ehcache.
          下面開始進(jìn)行配置
          首先是ehcache的配置文件

          <?xml version="1.0" encoding="UTF-8"?>  
          <ehcache>  
               
          <diskStore path="/home/workspace/gzshine/trunk/ehcache"/>  
               
          <cache name="DEFAULT_CACHE"  
                   maxElementsInMemory
          ="10000"  
                   eternal
          ="false"  
                   timeToIdleSeconds
          ="3600"  
                   timeToLiveSeconds
          ="3600"  
                   overflowToDisk
          ="true"/>  
          </ehcache> 

          這個(gè)的DEFAULT_CACHE是默認(rèn)配置,最大的緩存數(shù)為10000,時(shí)間為一個(gè)小時(shí)

          接下來的是spring下的配置

          <?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"  
               xmlns:tx
          ="http://www.springframework.org/schema/tx"  
               xmlns:context
          ="http://www.springframework.org/schema/context"  
               xsi:schemaLocation
          ="  
                  http://www.springframework.org/schema/beans  
                  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
                  http://www.springframework.org/schema/tx  
                  http://www.springframework.org/schema/tx/spring-tx-2.5.xsd  
                  http://www.springframework.org/schema/aop  
                  http://www.springframework.org/schema/aop/spring-aop-2.5.xsd  
                  http://www.springframework.org/schema/context  
                  http://www.springframework.org/schema/context/spring-context-2.5.xsd"
          >  
             
          <!-- ##############  aspectj 4 ehcache   ############# -->  
                 
               
          <aop:aspectj-autoproxy proxy-target-class="true"/>  
               
          <bean id = "methodCacheAspectJ" class="com.***.shine.aspectj.MethodCacheAspectJ" >  
                   
          <property name="cache">  
                       
          <ref local="methodCache" />  
                   
          </property>  
               
          </bean>  
                 
               
          <bean id="cacheManager"  
                   class
          ="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">  
                   
          <property name="configLocation">  
                       
          <value>classpath:ehcache.xml</value>  
                   
          </property>  
               
          </bean>  
                 
               
          <!-- 定義ehCache的工廠,并設(shè)置所使用的Cache name -->  
                 
               
          <bean id="methodCache"  
                   class
          ="org.springframework.cache.ehcache.EhCacheFactoryBean">  
                   
          <property name="cacheManager">  
                       
          <ref local="cacheManager" />  
                   
          </property>  
                   
          <property name="cacheName">  
                       
          <value>DEFAULT_CACHE</value>  
                   
          </property>  
               
          </bean> 

          <aop:aspectj-autoproxy proxy-target-class="true"/>
          是為aspectj在所有class下開啟自動動態(tài)代理
          <bean id="cacheManager">指定剛剛的ehcache配置文件


          接下來編寫一個(gè)自定義的annotation

           package com.***.shine.cache;  
             
           
          import java.lang.annotation.Documented;  
           
          import java.lang.annotation.ElementType;  
           
          import java.lang.annotation.Retention;  
           
          import java.lang.annotation.RetentionPolicy;  
           
          import java.lang.annotation.Target;  
             
           @Target({ElementType.METHOD,ElementType.TYPE})  
           @Retention(RetentionPolicy.RUNTIME)  
           @Documented  
           
          public @interface MethodCache {  
               
          int second() default 0;   
           } 

          <bean id = "methodCacheAspectJ">是一個(gè)aspectj進(jìn)行Pointcuts和Advice的類需注入methodCache

           package com.***.shine.aspectj;  
             
           @Aspect  
           
          public class MethodCacheAspectJ {  
               Log logger 
          = LogFactory.getLog(MethodCacheAspectJ.class);  
                 
               
          private Cache cache;  
                 
               
          /** 
                * 設(shè)置緩存名 
                
          */  
               
          public void setCache(Cache cache) {  
                   
          this.cache = cache;  
               }   
                 
               @Pointcut(
          "@annotation(com.***.shine.cache.MethodCache)")  
               
          public void methodCachePointcut(){    
               }  
                 
               @Around(
          "methodCachePointcut()")  
               
          public Object methodCacheHold(ProceedingJoinPoint joinPoint) throws Throwable{  
                   String targetName 
          = joinPoint.getTarget().getClass().getName();  
                   String methodName 
          = joinPoint.getSignature().getName();  
                   Object[] arguments 
          = joinPoint.getArgs();  
                   Object result 
          = null;  
                   String cacheKey 
          = getCacheKey(targetName, methodName, arguments);  
                   Element element 
          = cache.get(cacheKey);  
                   
          if (element == null) {  
                       
          try{  
                           result 
          = joinPoint.proceed();  
                       }
          catch(Exception e){  
                           logger.info(e);  
                       }  
                       
          if(result!=null){  
                           
          try{  
                               element 
          = new Element(cacheKey, (Serializable) result);  
                               Class targetClass 
          = Class.forName(targetName);  
                               Method[] method 
          = targetClass.getMethods();  
                               
          int second = 0;  
                               
          for(Method m:method){  
                                   
          if (m.getName().equals(methodName)) {  
                                       Class[] tmpCs 
          = m.getParameterTypes();  
                                       
          if(tmpCs.length==arguments.length){  
                                           MethodCache methodCache 
          = m.getAnnotation(MethodCache.class);  
                                           second 
          = methodCache.second();  
                                           
          break;  
                                       }  
                                   }  
                               }  
                               
          if(second>0){ // annotation沒有設(shè)second值則使用ehcache.xml中自定義值  
                                   element.setTimeToIdle(second);  
                                   element.setTimeToLive(second);  
                               }  
                               cache.put(element);  
                           }
          catch(Exception e){  
                               logger.info(
          "!!!!!!!!!"+cacheKey+"!!!!!!!!!未能執(zhí)行方法緩存"+e);  
                           }  
                       }  
                   }  
                   
          return element.getValue();  
               }  
             
                
          private String getCacheKey(String targetName, String methodName,  
                       Object[] arguments) {  
                   StringBuffer sb 
          = new StringBuffer();  
                   sb.append(targetName).append(
          ".").append(methodName);  
                   
          if ((arguments != null&& (arguments.length != 0)) {  
                       
          for (int i = 0; i < arguments.length; i++) {  
                           
          if (arguments[i] instanceof Date) {  
                               sb.append(
          ".").append(  
                                       DateUtil.datetoString((Date) arguments[i]));  
                           } 
          else {  
                               sb.append(
          ".").append(arguments[i]);  
                           }  
                       }  
                   }  
                   
          return sb.toString();  
               }  
           } 


          @Pointcut("@annotation(com.netease.shine.cache.MethodCache)")
          對有應(yīng)用com.netease.shine.cache.MethodCache進(jìn)行注解的方法進(jìn)行橫切面攔截
          @Around("methodCachePointcut()")
          并在Advice中處理這個(gè)Pointcut,這里的的Advice使用的是Around(環(huán)繞通知)
          String cacheKey = getCacheKey(targetName, methodName, arguments);
          接下來使用類型,方法名,參數(shù)為key進(jìn)入緩存處理
          Element element = cache.get(cacheKey);
          當(dāng)然如果在cache隊(duì)列中取得非null對象則直接返回該對象
          MethodCache methodCache = m.getAnnotation(MethodCache.class);
          second = methodCache.second();
          取得second的值(緩存的時(shí)間,如在@annotation中無重寫只為int second() default 0)
          element.setTimeToIdle(second);
          element.setTimeToLive(second);
          如果非零則重新設(shè)置緩存時(shí)間

          @MethodCache(second=300)  
          public List<Sort> getSort(int type,int parentid){  
               System.out.println(
          "!!!!!!!!!!!!!沒緩存到");  
               Row row 
          = new Row();  
               row.put(
          "type", type);  
               row.put(
          "parentid", parentid);  
               
          return (List<Sort>)gz_Template.queryForList("sort.getSort", row);  
           } 


          ----------------------------------------

          陳于喆
          Mail: chenyz@corp.netease.com

          posted on 2010-08-23 10:35 陳于喆 閱讀(8530) 評論(0)  編輯  收藏 所屬分類: spring

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 砚山县| 濮阳市| 南康市| 偏关县| 黄冈市| 贺兰县| 馆陶县| 富锦市| 汪清县| 杨浦区| 包头市| 皮山县| 博兴县| 鱼台县| 大同市| 丽江市| 石狮市| 亚东县| 富裕县| 永川市| 邢台市| 临安市| 开阳县| 德惠市| 南丰县| 汉中市| 阜平县| 集安市| 清丰县| 衡山县| 江津市| 辰溪县| 东兰县| 德庆县| 江永县| 佳木斯市| 交口县| 丰镇市| 永胜县| 宜黄县| 昌黎县|