标签:owa advice ace this flow eth day targe out
由于系统需求需 要对各个接口进行key-value缓存(以参数为key,返回的对象为value),
当然对于这种情况首先考虑到的是使用aop,前段时间看过 aspectj的一些介绍,
借此机会正好加以应用和体会一下,aspectj是AOP最早成熟的java实现,
它稍微扩展了一下java语言,增加了一些 keyword等,具体的aspectj的基本语法见这里,进行缓存的框架使用较成熟的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下的配置
<!-- ############## 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
@Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface MethodCache { int second() default 0; }
<bean id = "methodCacheAspectJ">是一个aspectj进行Pointcuts和Advice的类需注入methodCache
@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); }
使用自定义annotation接口进行aspectj动态缓存
标签:owa advice ace this flow eth day targe out
原文地址:http://www.cnblogs.com/anstoner/p/7514086.html