zoukankan      html  css  js  c++  java
  • 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(" 【写入Memcached缓存】" +
    " group={}" +
    " key={}" +
    " value={}" +
    " expiration={}",group,key, JSON.toJSON(result),expiration);
    } catch (Throwable e) {
    log.error("执行方法失败: {} -> {}", packageName, methodName);
    log.error("失败原因:{}",e.getMessage());
    }
    }else{
    // memcached中存在 直接返回
    log.info(" 【读取Memcached缓存】" +
    " group={}" +
    " key={}" +
    " value={}",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;
    }
    }
    --------------------- 

  • 相关阅读:
    Codefoces Gym 101652 【最大连续和】
    HYSBZ 4034 【树链剖分】+【线段树 】
    Codeforces Gym 101291C【优先队列】
    Codeforces gym 101291 M (最长交替子序列)【DP】
    HDU 3308 LCIS (经典区间合并)【线段树】
    POJ 3237 Tree (树链剖分+边权转点权)
    POJ 2763 Housewife Wind (树链剖分+边权转点权)
    P1054 等价表达式
    P1107 [BJWC2008]雷涛的小猫
    P1552 [APIO2012]派遣
  • 原文地址:https://www.cnblogs.com/ly570/p/10992441.html
Copyright © 2011-2022 走看看