在实际的开发框架中,需要用到缓存,很多时候,我们的缓存是基于ORM框架的缓存,使用起来不能满足实际情况
目前我们的开发是按照接口来开发的,需要在service 层就使用缓存,如CMS中的文章等等。故我们设计了基于AOP的缓存框架
不多说,直接贴代码
annotation:
package com.lsxin.framework.annotation;
import com.lsxin.framework.annotation.constant.CacheExpirationTime;
import com.lsxin.framework.annotation.constant.CacheType;
import java.lang.annotation.*;
/**
* ***************************************************************
* <pre>
* Copyright (c) 2016 –苏州利盛欣信息科技有限公司
* Title: com.lsxin.framwork.annotation
* Description:
* History:
* <p> 2016/3/21 init</p>
* ***************************************************************
* 2016/3/21 V1.0 guzhixiong New Files for framework
* </pre>
*/
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LsxCache {
/**
* 缓存类型
* @return
*/
CacheType cacheType() default CacheType.CACHE;
/**
* 缓存名称
* @return
*/
String cacheName();
/**
* 过期时间
* @return
*/
CacheExpirationTime expirationTime() default CacheExpirationTime.ONE_DAY;
}
缓存Aop 缓存的AOP是基于Annotation的
package com.lsxin.framework.support.spring;
import com.alibaba.fastjson.JSON;
import com.lsxin.framework.annotation.LsxCache;
import com.lsxin.framework.annotation.constant.CacheType;
import com.lsxin.framework.cache.LsxCacheManager;
import com.lsxin.framework.log.LsxLog;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
/**
* ***************************************************************
* <pre>
* Copyright (c) 2016 –苏州利盛欣信息科技有限公司
* Title: com.lsxin.framework.support.spring
* Description:缓存拦截Aop
* History:
* <p> 2016/3/24 init</p>
* ***************************************************************
* 2016/3/24 V1.0 guzhixiong New Files for framework
* </pre>
*/
@Aspect
public class CacheAop {
private LsxLog log = LsxLog.getInstance(MethodAop.class,"framework");
// 缓存
@Autowired(required = false)
private LsxCacheManager cacheManager;
@Pointcut("@annotation(com.lsxin.framework.annotation.LsxCache)")
public void cachePointcut() {
}
@Around("cachePointcut()&& @annotation(lsxCache)")
public Object aroundMethod(ProceedingJoinPoint joinPoint,LsxCache lsxCache) throws Throwable {
//原方法名
String methodName = joinPoint.getSignature().getName();
if(lsxCache !=null){
if (lsxCache.cacheType().equals(CacheType.CACHE)) {
Object[] arguments = joinPoint.getArgs();
String cacheKey = getCacheKey(lsxCache.cacheName(), methodName, arguments);
Object data = cacheManager.get(lsxCache.cacheName(),cacheKey);
if(data==null){
data = joinPoint.proceed();
cacheManager.set(lsxCache.cacheName(),cacheKey,data);
}
log.i("{} use cache: {} ",methodName,lsxCache.cacheName());
return data;
}
if(lsxCache.cacheType().equals(CacheType.CACHE_UPDATE)){
cacheManager.clear(lsxCache.cacheName());
log.i("{} clear cache: {}",methodName,lsxCache.cacheName());
}
}
return joinPoint.proceed();
}
private String getCacheKey(String className, String methodName, Object[] arguments) {
StringBuffer sb = new StringBuffer();
sb.append(className).append(".").append(methodName);
if ((arguments != null) && (arguments.length != 0)) {
for (int i = 0; i < arguments.length; i++) {
sb.append(".").append(JSON.toJSONString(arguments[i]));
}
}
return sb.toString();
}
public void setCacheManager(LsxCacheManager cacheManager) {
this.cacheManager = cacheManager;
}
}
Cache 接口类,在开发中,我们可以根据不同的情况实现不同的缓存(redis mongodb等) 即可
package com.lsxin.framework.cache;
import java.util.List;
/**
* ***************************************************************
* <pre>
* Copyright (c) 2016 –苏州利盛欣信息科技有限公司
* Title: com.lsxin.framwork.cache
* Description:缓存接口
* History:
* <p> 2016/3/22 init</p>
* ***************************************************************
* 2016/3/22 V1.0 guzhixiong New Files for framework
* </pre>
*/
public interface LsxCacheManager {
/**
* 设置缓存
* @param name
* @param key
* @param value
*/
public void set(String name, Object key, Object value) throws CacheException;
/**
* 获取缓存
* @param name
* @param key
* @return
*/
public Object get(String name,Object key) throws CacheException;
/**
* 获取缓存
* @param resultClass
* @param name
* @param key
* @param <T>
* @return
*/
public <T> T get(Class<T> resultClass, String name, Object key) throws CacheException;
/**
* 删除一个数据
* @param name
* @param key
*/
public void delete(String name, Object key) throws CacheException;
/**
* 批量删除
* @param name
* @param keys
*/
public void batchDelete(String name,List keys) throws CacheException;
/**
* 清空数据
* @param name
*/
public void clear(String name) throws CacheException;
/**
* 获取所有的缓存键值
* @param name
* @return
* @throws CacheException
*/
public List keys(String name) throws CacheException;
}
使用:
在使用的时候,只需要配置aop 如下图
在实际使用中只需要在对应的代码上面只需要打上cache 的注解即可,是不是很方便