AOP注解形式 整合memcache

Posted ly570

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AOP注解形式 整合memcache相关的知识,希望对你有一定的参考价值。

1.首先自定义注解 :添加缓存

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Memcached
// key的前缀 default=STATIC的可以使用OMS清理缓存
String prefix() default "STATIC_";
// key
String key() default "";
// 过滤
String conditions() default "true";
// 緩存分組
String group() default "hos-portal-mclient1";
// 缓存有效期 2天 单位s
int expiration() default 60 * 60 * 48;

2.切面类

@Aspect
public class MemCachedAop

private static final Logger log = LoggerFactory.getLogger(MemCachedAop.class);

@Value("$enable.static.cache")
private boolean enableCache;

@Pointcut("execution(* com.ylzinfo.hospital.portal.service.appservice.*.*.*(..))")
protected void appservicePointcut()

@Autowired
private ICacheClient cacheClient;

/**
* 写入或者读取缓存
* 仅针对有注解的且该包下的方法
*/
@Around("(@annotation(memcached) && appservicePointcut())")
public Object doMemcachedAround(ProceedingJoinPoint call, Memcached memcached) throws Throwable
String packageName = call.getSignature().getDeclaringTypeName();
String methodName = call.getSignature().getName();
log.info("执行方法: -> ", packageName, methodName);
//返回最终结果
Object result = null;
//校验conditions
if (null != memcached
&& checkConditions(call,memcached.conditions())
&& enableCache)
String key = resolvingKey(call,memcached.prefix(),memcached.key());
String group = memcached.group();
result = cacheClient.get(group, key);
if (null == result)
// memcached中不存在
try
//执行aop拦截的方法
result = call.proceed();
//获取注解配置memcached过期时间
int expiration = memcached.expiration();
cacheClient.put(group, key, result, expiration);
log.info("\n【写入Memcached缓存】" +
"\ngroup=" +
"\nkey=" +
"\nvalue=" +
"\nexpiration=",group,key, JSON.toJSON(result),expiration);
catch (Throwable e)
log.error("执行方法失败: -> ", packageName, methodName);
log.error("失败原因:",e.getMessage());

else
// memcached中存在 直接返回
log.info("\n【读取Memcached缓存】" +
"\ngroup=" +
"\nkey=" +
"\nvalue=",group,key,JSON.toJSON(result));

else
try
result = call.proceed();
catch (Throwable e)
log.error("执行方法失败: -> ", packageName, methodName);
log.error("失败原因:",e.getMessage());


return result;




/**
* 获取缓存的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);


/**
* 获取被拦截方法对象
*
* MethodSignature.getMethod() 获取的是顶层接口或者父类的方法对象
* 而缓存的注解在实现类的方法上
* 所以应该使用反射获取当前对象的方法对象
*/
public Method getMethod(ProceedingJoinPoint pjp)
//获取参数的类型
Object [] args=pjp.getArgs();
Class [] argTypes=new Class[pjp.getArgs().length];
for(int i=0;i<args.length;i++)
argTypes[i]=args[i].getClass();

Method method=null;
try
method=pjp.getTarget().getClass().getMethod(pjp.getSignature().getName(),argTypes);
catch (NoSuchMethodException e)
log.error(e.getMessage());
catch (SecurityException e)
log.error(e.getMessage());

return method;


/**
* 解析key
* @author zengfanqi
* @date 2019/5/6
* @param
* @return String
*/
public String resolvingKey(ProceedingJoinPoint call,String prefix,String key)

//如果key为空直接将方法名称作为key
String methodName = call.getSignature().getName();
if(StringUtils.isEmpty(key))
return prefix + methodName;


//判断key是否是spel表达式
if(key.startsWith("#"))
Method method=getMethod(call);
String parsekey = parseKey(key,method,call.getArgs());
if(StringUtils.isEmpty(parsekey))
parsekey = methodName;

key = prefix+parsekey;
else
key = prefix+key;

return key;


/**
* 校验conditions
* @author zengfanqi
* @date 2019/5/6
* @param
* @return
*/
public boolean checkConditions(ProceedingJoinPoint call,String conditions)
boolean flag = false;
Method method=getMethod(call);
String condition = parseKey(conditions,method,call.getArgs());
if("true".equals(condition))
flag = true;

return flag;


--------------------- 

以上是关于AOP注解形式 整合memcache的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot整合Mybatis多数据源 (AOP+注解)

spring中的aop注解(整合junit测试)

JAVAEE——spring02:使用注解配置springsts插件junit整合测试和aop演示

Spring4——基于注解形式的aop实现基于Schema形式的aop实现

JAVAEE框架整合技术之Spring02-AOP面向切面编程技术

JAVAEE框架整合技术之Spring02-AOP面向切面编程技术