在Spring Framework中,默认提供的@Cache系列Annotation,比较死板,不能适应redis的多数据结构,但其SPEL的方式,非常值得借鉴。所以自定义了@RedisCache annotation,并且可以使用SPEL,以下代码为部分实现。
- 定义Annotation: RedisCachePut
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RedisCachePut {
String key();
String suffixKey() default "";
long expired() default 0;
}
- 定义Aspect:RedisCaheAop,在spring boot中定义AOP非常简单:
- 在pom.xml中增加aop依赖,因为在application.properties中spring.aop.auto=ture,是默认开启的,所以无需在做特殊处理
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
- 在实现类上,只需要加上@Aspect 和 @Component两个注解即可
@Aspect
@Component
public class RedisCacheAop {
private static final Logger logger = LoggerFactory.getLogger(RedisCacheAop.class);
@Autowired
private BaseRedisDao redisDao;
}
- 在RedisCacheAop中增加相应方法:
@Around("@annotation(redisCachePut)")
public Object doRedisCachePut(ProceedingJoinPoint joinPoint,RedisCachePut redisCachePut) throws Throwable{
Object value = joinPoint.proceed();
if(value!=null){
String key = redisCachePut.key();
String suffixKey = redisCachePut.suffixKey();
long expired = redisCachePut.expired();
key = key + generateKey(suffixKey, joinPoint);
redisDao.set(key, value,expired);
}
return value;
}
- generateKey为自定义的方法,目的是使用SPEL解析相应的表达式
private String generateKey(String suffixKey ,ProceedingJoinPoint pjp){
String key = "";
if(StringUtils.isNotEmpty(suffixKey)){
Method method = parseMethod(pjp);
key = parseKey(suffixKey,method,pjp.getArgs());
}
return key;
}
private Method parseMethod(ProceedingJoinPoint pjp){
Method method=null;
try {
MethodSignature methodSignature = (MethodSignature)pjp.getSignature();//get method info from interface or parent class
Class[] argTypes = methodSignature.getMethod().getParameterTypes();//get method parameter type from interface or parent class
method=pjp.getTarget().getClass().getMethod(pjp.getSignature().getName(),argTypes);
} catch (NoSuchMethodException e) {
logger.info("parseMehthod was failed in RedisCacheAop Calss");
logger.info(e.toString());
} catch (SecurityException e) {
logger.info("parseMehthod was failed in RedisCacheAop Calss");
logger.info(e.toString());
}
return method;
}
private String parseKey(String key,Method method,Object[] args){
//Get to intercept method parameter list (using the Spring support library)
LocalVariableTableParameterNameDiscoverer discover = new LocalVariableTableParameterNameDiscoverer();
String[] paraNameArr=discover.getParameterNames(method);
//Analysis using SPEL key
ExpressionParser parser = new SpelExpressionParser();
//The SPEL context
StandardEvaluationContext context = new StandardEvaluationContext();
//The method of parameter in the SPEL context
for(int i=0;i<paraNameArr.length;i++){
context.setVariable(paraNameArr[i], args[i]);
}
String parseKey = parser.parseExpression(key).getValue(context,String.class);
return parseKey;
}
- 使用
@RedisCachePut(key=demoEntityKey,suffixKey="#demoEntity.id",expired=300)
public DemoEntity save(DemoEntity demoEntity){
DemoEntity resultDemo = getDemoDao().save(demoEntity);
return resultDemo;
}
参考:http://www.programering.com/a/MjNzUjNwATc.html