AOP面向切入实现service层嵌入缓存 http://my.oschina.net/vill/blog/550715
//放入缓存注解 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Inherited public @interface Cacheable { //放入 String key(); //缓存key String fieldKey();// field值 int expireTime() default 3600; } //从缓存中销毁注解 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface CacheEvict { //销毁 String key(); String[] fieldKey(); int expireTime() default 3600; } Aspect类 //环绕切入 @Around(value = "@annotation(com.xx.cache.annotation.Cacheable)") public Object cache(ProceedingJoinPoint pjp) { Object result = null; Method method = getMethod(pjp); Cacheable cacheable = method.getAnnotation(Cacheable.class); String fieldKey = cacheable.fieldKey(); if (cacheable.fieldKey().indexOf("#") == 0) {//动态变量存入方式 fieldKey = parseKey(cacheable.fieldKey(), method, pjp.getArgs()); } if (useCache) {//判断是否开启缓存 开启缓存 从缓存获取 result //获取方法的返回类型,让缓存可以返回正确的类型 Class returnType = ((MethodSignature) pjp.getSignature()).getReturnType(); //使用redis 的hash进行存取,易于管理 // result = JedisUtils.hget(cacheable.key(), fieldKey,method.getReturnType()); result = JedisUtils.hget(cacheable.key(), fieldKey, returnType); if (result == null) { try { result = pjp.proceed(); // Assert.notNull(fieldKey); JedisUtils.hset(cacheable.key(), fieldKey, result); logger.debug("The " + cacheable.key() + " add to redis, the fieldKey is " + fieldKey); } catch (Throwable e) { e.printStackTrace(); } } return result; } try { return pjp.proceed(); } catch (Throwable throwable) { throwable.printStackTrace(); return null; } } //环绕切入 @Around(value = "@annotation(com.xx.cache.annotation.CacheEvict)") public Object evict(ProceedingJoinPoint pjp) { //和cache类似,使用Jedis.hdel()删除缓存即可 if (useCache) {//判断是否开启缓存 Method method = getMethod(pjp); CacheEvict cacheEvict = method.getAnnotation(CacheEvict.class); String[] fieldKeys = cacheEvict.fieldKey(); int deleteSuccessFlag = 0; for (String fieldKey : fieldKeys) { if (fieldKey.indexOf("#") == 0) {//动态变量存入方式 String t = fieldKey; fieldKey = parseKey(fieldKey, method, pjp.getArgs()); if (fieldKey == null) { logger.error("cache evict fieldkey {} connot be null, that may be cause data connot sync ", t); t = null; } } deleteSuccessFlag += JedisUtils.hdel(cacheEvict.key(), fieldKey == null ? "" : fieldKey); logger.debug("The reference fieldkey: " + fieldKey + " for " + cacheEvict.key() + " has been delete from redis"); } logger.debug("Delete " + deleteSuccessFlag + " " + cacheEvict.key() + "from redis"); } try { return pjp.proceed(); } catch (Throwable e) { e.printStackTrace(); return null; } } /** * 获取缓存的key * key 定义在注解上,支持SPEL表达式 * * @param key * @param method * @param args * @return */ private String parseKey(String key, Method method, Object[] args) { //获取被拦截方法参数名列表(使用Spring支持类库) LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer(); String[] paraNameArr = u.getParameterNames(method); //使用SPEL进行key的解析 ExpressionParser parser = new SpelExpressionParser(); //SPEL上下文 StandardEvaluationContext context = new StandardEvaluationContext(); //把方法参数放入SPEL上下文中 for (int i = 0; i < paraNameArr.length; i++) { context.setVariable(paraNameArr[i], args[i]); } return parser.parseExpression(key).getValue(context, String.class); }
使用,在service调用前使用:
@Cacheable(key = "biz_member",fieldKey = "#id") public Member get(String id) { return super.get(id); } @CacheEvict(key = "member",fieldKey = {"#member.id","#member.account"}) public Serializable save(Member member) { return dao.insert(member); } @CacheEvict(key = "member",fieldKey = {"#member.id","#member.account"}) public void delete(Member member) { dao.delete(member); }
转载请声明。