`
piperzero
  • 浏览: 3493001 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

使用自定义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的配置文件
<?xmlversion="1.0"encoding="UTF-8"?>
<ehcache>
<diskStorepath="/home/workspace/gzshine/trunk/ehcache"/>
<cachename="DEFAULT_CACHE"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="3600"
overflowToDisk="true"/>
</ehcache>

这个的DEFAULT_CACHE是默认配置,最大的缓存数为10000,时间为一个小时
接下来的是spring下的配置
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="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">

<!--##############aspectj4ehcache#############-->
<aop:aspectj-autoproxyproxy-target-class="true"/>
<beanid="methodCacheAspectJ"class="com.***.shine.aspectj.MethodCacheAspectJ">
<propertyname="cache">
<reflocal="methodCache"/>
</property>
</bean>
<beanid="cacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<propertyname="configLocation">
<value>classpath:ehcache.xml</value>
</property>
</bean>
<!--定义ehCache的工厂,并设置所使用的Cachename-->
<beanid="methodCache"
class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<propertyname="cacheManager">
<reflocal="cacheManager"/>
</property>
<propertyname="cacheName">
<value>DEFAULT_CACHE</value>
</property>
</bean>

<aop:aspectj-autoproxy
proxy-target-class="true"/>
是为aspectj在所有class下开启自动动态代理
<bean id="cacheManager">指定刚刚的ehcache配置文件
接下来编写一个自定义的annotation
packagecom.***.shine.cache;
importjava.lang.annotation.Documented;
importjava.lang.annotation.ElementType;
importjava.lang.annotation.Retention;
importjava.lang.annotation.RetentionPolicy;
importjava.lang.annotation.Target;
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public@interfaceMethodCache{
intsecond()default0;

<bean id =
"methodCacheAspectJ">是一个aspectj进行Pointcuts和Advice的类需注入methodCache
packagecom.***.shine.aspectj;
@Aspect
publicclassMethodCacheAspectJ{
Loglogger=LogFactory.getLog(MethodCacheAspectJ.class);
privateCachecache;

publicvoidsetCache(Cachecache){
this.cache=cache;

@Pointcut("@annotation(com.***.shine.cache.MethodCache)")
publicvoidmethodCachePointcut(){

@Around("methodCachePointcut()")
publicObjectmethodCacheHold(ProceedingJoinPointjoinPoint)throwsThrowable{
StringtargetName=joinPoint.getTarget().getClass().getName();
StringmethodName=joinPoint.getSignature().getName();
Object[]arguments=joinPoint.getArgs();
Objectresult=null;
StringcacheKey=getCacheKey(targetName,methodName,arguments);
Elementelement=cache.get(cacheKey);
if(element==null){
try{
result=joinPoint.proceed();
}catch(Exceptione){
logger.info(e);
if(result!=null){
try{
element=newElement(cacheKey,(Serializable)result);
ClasstargetClass=Class.forName(targetName);
Method[]method=targetClass.getMethods();
intsecond=0;
for(Methodm:method){
if(m.getName().equals(methodName)){
Class[]tmpCs=m.getParameterTypes();
if(tmpCs.length==arguments.length){
MethodCachemethodCache=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(Exceptione){
logger.info("!!!!!!!!!"+cacheKey+"!!!!!!!!!未能执行方法缓存"+e);
}
returnelement.getValue();

privateStringgetCacheKey(StringtargetName,StringmethodName,
Object[]arguments){
StringBuffersb=newStringBuffer();
sb.append(targetName).append(".").append(methodName);
if((arguments!=null)&&(arguments.length!=0)){
for(inti=0;i<arguments.length;i++){
if(arguments[i]instanceofDate){
sb.append(".").append(
DateUtil.datetoString((Date)arguments[i]));
}else{
sb.append(".").append(arguments[i]);
}
returnsb.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)
publicList<Sort>getSort(inttype,intparentid){

System.out.println("!!!!!!!!!!!!!没缓存到");
Rowrow=newRow();
row.put("type",type);
row.put("parentid",parentid);
return(List<Sort>)gz_Template.queryForList("sort.getSort",row);
----------------------------------------
陈于喆
Mail: chenyz@corp.netease.com
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics