公司有一个项目,使用dubbo提供服务,接口大部分是查询数据接口,数据需要redis缓存以减少服务器压力,如果每个接口都手动写代码实现redis缓存的话,工作量很大,因此思考只用一套代码实现redis功能注入,无需修改业务代码。
先定义一个注解:
@Target(METHOD)
@Retention(RUNTIME)
public @interface RedisCache {
long time() default 1;
TimeUnit timeunit() default TimeUnit.DAYS;
}
需要用到切面,在pom中加入:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.10</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.10</version>
</dependency>
定义切面类RedisCacheAspect,并在spring配置文件中注入:
@Around(value="@annotation(com.mycache.RedisCache)")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
//System.out.println("环绕通知前....");
Class clazz = joinPoint.getTarget().getClass();
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
StringBuilder keyB = new StringBuilder();
keyB.append(clazz.getSimpleName()).append("_").append(method.getName());
String[] argNames = null;
Object[] argValues = null;
LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
argNames = u.getParameterNames(method);
argValues = joinPoint.getArgs();
if(argNames.length==argValues.length){
for (int i = 0; i < argNames.length; i++) {
keyB.append("_").append(argValues[i]);
}
}
String key = keyB.toString();
Object obj = redissonClient.getBucket(key).get();
if(obj!=null){
return obj;
}
else{
obj = joinPoint.proceed();
}
if(obj!=null){
if(method.isAnnotationPresent(RedisCache.class)){
RedisCache redisCache = method.getAnnotation(RedisCache.class);
redissonClient.getBucket(key).set(obj, redisCache.time(), redisCache.timeunit());
}
}
//System.out.println("环绕通知后....");
return obj;
}
最后在业务方法上加入注解:
@Override
@RedisCache(time = 10,timeunit = TimeUnit.DAYS)
public PageInfo<Category> getRadioCategories(Integer offset, Integer limit) throws BaseDubboException, BaseDubboServerException {
JSONObject params = new JSONObject();
params.put("offset", RadioV2CheckUtil.checkOffset(offset));
params.put("limit", RadioV2CheckUtil.checkLimit(limit));
String result = spService.call(BIFROST_SP_URL.RADIO_CATEGORIES, params);
return RadioUtil.getJsonObjectPageInfo(result,Category.class);
}
注解参数中可以根据不同接口的需求配置不同的redis超时时间。如果将来业务有变化,不需要缓存了,去掉注解就可,非常方便。