最近在写自己框架的时候研究了下ecache缓存技术,我在纠结使用ecache还是使用redis呢,因为redis是基于内存的缓存技术,当然他们的应用场景不同。我更加倾向于redis,所以,自己写了基于spring aop的redis注解,本来想用ecache的注解方式实现redis注解,发现工作量庞大,所以,就实现了一个最初版:
注解
package com.nise.common.framework.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 缓存切面
*
*
* @author gerry
* @version 1.0, 2016年1月12日下午5:40:02
* @since com.gerry.link 1.0
* @see com.nise.common.framework.redis.RequireCacheInterceptor
*/
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface RequireCache {
String value();
String key() default "";
/**
* 设置秒,默认5分钟
*
* @return
* @see
*/
int seconds() default 300;
}
package com.nise.common.framework.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 删除缓存
*
*
* @author gerry
* @version 1.0, 2016年1月13日上午9:35:18
* @since com.gerry.link 1.0
* @see com.nise.common.framework.redis.DeleteCacheInterceptor
*/
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface DeleteCache {
String value();
String key() default "";
}
package com.nise.common.framework.redis;
import java.lang.reflect.Method;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.nise.common.framework.annotations.RequireCache;
import com.nise.common.framework.constants.CommonConstants;
import com.nise.common.framework.utils.EmptyUtils;
/**
* 缓存注解
*
*
* @author gerry
* @version 1.0, 2016年1月12日下午5:44:39
* @since com.gerry.link 1.0
*/
@Slf4j
public class RequireCacheInterceptor implements MethodInterceptor {
@Autowired
private RedisManager<String, Object> redis;
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod();
RequireCache cache = method.getAnnotation(RequireCache.class);
if (EmptyUtils.isEmpty(cache)) {// 不需要缓存
return invocation.proceed();
}
Object[] params = invocation.getArguments();
// key的规则就是:当前执行类的名字+"_"+方法名字+"_"+value+"_"+key+key的值
StringBuffer sb = new StringBuffer(cache.value()).append(CommonConstants.SYMBOL_UNDERLINE).append(invocation.getThis().getClass().getName()).append(CommonConstants.SYMBOL_UNDERLINE)
.append(method.getName());
if (EmptyUtils.isNotEmpty(cache.key()) && StringUtils.startsWith(cache.key(), CommonConstants.SYMBOL_DELIMITER)) {
sb.append(CommonConstants.SYMBOL_UNDERLINE).append(params[0]).append(CommonConstants.SYMBOL_UNDERLINE).append(cache.key());
}
Object obj = redis.getObjectByKey(sb.toString());// 先从redis中找,如果有,则直接返回,否则查询保存redis
if (EmptyUtils.isNotEmpty(obj)) {
log.info("根据key[" + sb.toString() + "]从缓存中获取数据");
return obj;
}
obj = invocation.proceed();
if (EmptyUtils.isNotEmpty(obj)) {
log.info("根据key[" + sb.toString() + "]把数据放入缓存");
redis.saveObjectBySeconds(sb.toString(), obj, cache.seconds());
}
return obj;
}
}
package com.nise.common.framework.redis;
import java.lang.reflect.Method;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.nise.common.framework.annotations.DeleteCache;
import com.nise.common.framework.constants.CommonConstants;
import com.nise.common.framework.utils.EmptyUtils;
/**
* 缓存注解
*
*
* @author gerry
* @version 1.0, 2016年1月12日下午5:44:39
* @since com.gerry.link 1.0
*/
@Slf4j
public class DeleteCacheInterceptor implements MethodInterceptor {
@Autowired
private RedisManager<String, Object> redis;
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod();
DeleteCache cache = method.getAnnotation(DeleteCache.class);
if (EmptyUtils.isNotEmpty(cache)) {
Object[] params = invocation.getArguments();
StringBuffer sb = new StringBuffer(cache.value()).append(CommonConstants.SYMBOL_UNDERLINE).append(invocation.getThis().getClass().getName()).append(CommonConstants.SYMBOL_UNDERLINE)
.append(method.getName());
if (EmptyUtils.isNotEmpty(cache.key()) && StringUtils.startsWith(cache.key(), CommonConstants.SYMBOL_DELIMITER)) {
sb.append(CommonConstants.SYMBOL_UNDERLINE).append(params[0]).append(CommonConstants.SYMBOL_UNDERLINE).append(cache.key());
}
redis.deleteObjectByKey(sb.toString());
log.info("根据key[" + sb.toString() + "]删除缓存数据");
}
return invocation.proceed();
}
}
spring配置
<bean id="deleteCacheInterceptor" class="com.nise.common.framework.redis.DeleteCacheInterceptor">
</bean>
<aop:config>
<!--切入点 -->
<aop:pointcut id="lockPointcut" expression="execution(* com.gerry.common.*.service.impl.*.*(..))" />
<!--在该切入点使用自定义拦截器 -->
<aop:advisor pointcut-ref="lockPointcut" advice-ref="requireCacheInterceptor" order="1" />
</aop:config>
<aop:config>
<!--切入点 -->
<aop:pointcut id="lockPointcut" expression="execution(* com.gerry.common.*.service.impl.*.*(..))" />
<!--在该切入点使用自定义拦截器 -->
<aop:advisor pointcut-ref="lockPointcut" advice-ref="deleteCacheInterceptor" order="2" />
</aop:config>
当然这里的RedisManager也是我自己实现的。
希望有想法的有志青年,可以和我一起实现redis缓存注解功能,目前我这个只是雏形,当然了,这个雏形已经可以进行业务应用了。