使用自定义annotation接口进行aspectj动态缓存
生活随笔
收集整理的這篇文章主要介紹了
使用自定义annotation接口进行aspectj动态缓存
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
由于系統需求需
要對各個接口進行key-value緩存(以參數為key,返回的對象為value),當然對于這種情況首先考慮到的是使用aop,前段時間看過
aspectj的一些介紹,借此機會正好加以應用和體會一下,aspectj是AOP最早成熟的java實現,它稍微擴展了一下java語言,增加了一些
keyword等,具體的aspectj的基本語法見[ur=http://today.java.net/pub/a/today/2003/12
/26/ch3AspectJSyntaxBasics.html]這里[/url],進行緩存的框架使用較成熟的ehcache.
首先是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>?
這個的DEFAULT_CACHE是默認配置,最大的緩存數為10000,時間為一個小時
接下來的是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的工廠,并設置所使用的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下開啟自動動態代理
<bean id="cacheManager">指定剛剛的ehcache配置文件
接下來編寫一個自定義的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">是一個aspectj進行Pointcuts和Advice的類需注入methodCache
?package?com.***.shine.aspectj;??
?@Aspect??
?public?class?MethodCacheAspectJ?{??
?????Log?logger?=?LogFactory.getLog(MethodCacheAspectJ.class);??
?????private?Cache?cache;??
???????
?????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沒有設second值則使用ehcache.xml中自定義值??
?????????????????????????element.setTimeToIdle(second);??
?????????????????????????element.setTimeToLive(second);??
?????????????????????cache.put(element);??
?????????????????}catch(Exception?e){??
?????????????????????logger.info("!!!!!!!!!"+cacheKey+"!!!!!!!!!未能執行方法緩存"+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)")
對有應用com.netease.shine.cache.MethodCache進行注解的方法進行橫切面攔截
@Around("methodCachePointcut()")
并在Advice中處理這個Pointcut,這里的的Advice使用的是Around(環繞通知)
String cacheKey = getCacheKey(targetName, methodName,
arguments);
接下來使用類型,方法名,參數為key進入緩存處理
Element element = cache.get(cacheKey);
當然如果在cache隊列中取得非null對象則直接返回該對象
MethodCache methodCache = m.getAnnotation(MethodCache.class);
second = methodCache.second();
取得second的值(緩存的時間,如在@annotation中無重寫只為int second() default 0)
element.setTimeToIdle(second);
element.setTimeToLive(second);
如果非零則重新設置緩存時間
@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
要對各個接口進行key-value緩存(以參數為key,返回的對象為value),當然對于這種情況首先考慮到的是使用aop,前段時間看過
aspectj的一些介紹,借此機會正好加以應用和體會一下,aspectj是AOP最早成熟的java實現,它稍微擴展了一下java語言,增加了一些
keyword等,具體的aspectj的基本語法見[ur=http://today.java.net/pub/a/today/2003/12
/26/ch3AspectJSyntaxBasics.html]這里[/url],進行緩存的框架使用較成熟的ehcache.
首先是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>?
這個的DEFAULT_CACHE是默認配置,最大的緩存數為10000,時間為一個小時
接下來的是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的工廠,并設置所使用的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下開啟自動動態代理
<bean id="cacheManager">指定剛剛的ehcache配置文件
接下來編寫一個自定義的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">是一個aspectj進行Pointcuts和Advice的類需注入methodCache
?package?com.***.shine.aspectj;??
?@Aspect??
?public?class?MethodCacheAspectJ?{??
?????Log?logger?=?LogFactory.getLog(MethodCacheAspectJ.class);??
?????private?Cache?cache;??
???????
?????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沒有設second值則使用ehcache.xml中自定義值??
?????????????????????????element.setTimeToIdle(second);??
?????????????????????????element.setTimeToLive(second);??
?????????????????????cache.put(element);??
?????????????????}catch(Exception?e){??
?????????????????????logger.info("!!!!!!!!!"+cacheKey+"!!!!!!!!!未能執行方法緩存"+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)")
對有應用com.netease.shine.cache.MethodCache進行注解的方法進行橫切面攔截
@Around("methodCachePointcut()")
并在Advice中處理這個Pointcut,這里的的Advice使用的是Around(環繞通知)
String cacheKey = getCacheKey(targetName, methodName,
arguments);
接下來使用類型,方法名,參數為key進入緩存處理
Element element = cache.get(cacheKey);
當然如果在cache隊列中取得非null對象則直接返回該對象
MethodCache methodCache = m.getAnnotation(MethodCache.class);
second = methodCache.second();
取得second的值(緩存的時間,如在@annotation中無重寫只為int second() default 0)
element.setTimeToIdle(second);
element.setTimeToLive(second);
如果非零則重新設置緩存時間
@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
總結
以上是生活随笔為你收集整理的使用自定义annotation接口进行aspectj动态缓存的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言快速幂取模算法小结
- 下一篇: Duff in Love