redis实际应用_AOP_注解

参考文章:http://blog.csdn.net/zhanngle/article/details/41077423

1:注解

1:标注在方法上的注解,让spring可以找到将哪个方法的参数当做key,返回值当做value
package com.fengyong.base.beans.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 类描述:
 *
 * @author fengyong
 * @version 1.0
 * @since 1.0
 * Created by fengyong on 16/9/30 下午5:25.
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Cacheable {
    public enum KeyMode{
        CACHEKEY,    //只有加了@CacheKey的参数,才加入key后缀中
        BASIC,      //只有基本类型参数,才加入key后缀中,如:String,Integer,Long,Short,Boolean
        ALL;        //所有参数都加入key后缀
    }

    public String key() default "";     //缓存key
    public KeyMode keyMode() default KeyMode.ALL;       //key的后缀模式
    public int expire() default 0;      //缓存多少秒,默认无限期
}
2:标注在参数上的注解
package com.fengyong.base.beans.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 类描述:
 *
 * @author fengyong
 * @version 1.0
 * @since 1.0
 * Created by fengyong on 16/9/30 下午5:28.
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface CacheKey {
}

2:AOP配置

<bean id="redisCacheAop" class="com.system.aop.RedisCacheAop"></bean>
    <aop:config>
        <!-- 后置通知 -->
        <aop:aspect ref="redisCacheAop">
            <aop:around method="cached"  pointcut="@annotation(cache))" ></aop:around>
        </aop:aspect>
    </aop:config>

3:AOP类

package com.system.aop;

import com.fengyong.base.beans.Po;
import com.fengyong.base.beans.annotation.CacheKey;
import com.fengyong.base.beans.annotation.Cacheable;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.concurrent.TimeUnit;

/**
 * 类描述:
 *
 * @author fengyong
 * @version 1.0
 * @since 1.0
 * Created by fengyong on 16/10/1 上午8:48.
 */
public class RedisCacheAop {
    @Autowired
    private RedisTemplate redisTemplate;

    //@Around("@annotation(cache)")  可用配置代替pointcut="@annotation(cache))"
    public Object cached(final ProceedingJoinPoint pjp, Cacheable cache) throws Throwable {

        String key = getCacheKey(pjp, cache);
        ValueOperations<String, Object> valueOper = redisTemplate.opsForValue();
        Object value = valueOper.get(key);    //从缓存获取数据
        if (value != null) return value;       //如果有数据,则直接返回

        value = pjp.proceed();      //跳过缓存,到后端查询数据
        if (cache.expire() <= 0) {      //如果没有设置过期时间,则无限期缓存
            valueOper.set(key, value);
        } else {                    //否则设置缓存时间
            valueOper.set(key, value, cache.expire(), TimeUnit.SECONDS);
        }
        return value;
    }

    /**
     * 获取缓存的key值
     *
     * @param pjp
     * @param cache 注解
     * @return
     */
    private String getCacheKey(ProceedingJoinPoint pjp, Cacheable cache) throws Exception {

        StringBuilder buf = new StringBuilder();
        buf.append(pjp.getSignature().getDeclaringTypeName()).append(".").append(pjp.getSignature().getName());//获取包名,类名,方法名
        if (cache.key().length() > 0)
            buf.append(".").append(cache.key());//额外添加的key,,防止有重复的key

        Object[] args = pjp.getArgs();
        if (cache.keyMode() == Cacheable.KeyMode.CACHEKEY) {
            //Annotation[][] pas=((MethodSignature)pjp.getSignature()).getMethod().getParameterAnnotations(); //这里获取的可能是代理对象,所以拿不到注解对象
            Annotation[][] pas = pjp.getTarget().getClass().getMethod(pjp.getSignature().getName(),
                    ((MethodSignature) pjp.getSignature()).getParameterTypes()).getParameterAnnotations();
            for (int i = 0; i < pas.length; i++) {
                for (Annotation an : pas[i]) {
                    if (an instanceof CacheKey) {
                        getAllKey(buf, args[i]);
                        break;
                    }
                }
            }
        } else if (cache.keyMode() == Cacheable.KeyMode.BASIC) {
            for (Object arg : args)
                getBasicKey(buf, arg);
        } else if (cache.keyMode() == Cacheable.KeyMode.ALL) {
            for (Object arg : args)
                getAllKey(buf, arg);
        }
        return buf.toString();
    }

    /**
     * po实体类
     *
     * @param buf
     * @param arg
     * @throws IllegalAccessException
     */
    private void getAllKey(StringBuilder buf, Object arg) throws IllegalAccessException {
        if (arg instanceof Po)
            buf.append(".").append(((Po) arg).cacheString());
        else
            buf.append(".").append(arg.toString());
    }

    /**
     * 基本类型
     *
     * @param buf
     * @param arg
     */
    private void getBasicKey(StringBuilder buf, Object arg) {
        if (arg instanceof String) {
            buf.append(".").append(arg);
        } else if (arg instanceof Integer || arg instanceof Long || arg instanceof Short) {
            buf.append(".").append(arg.toString());
        } else if (arg instanceof Boolean) {
            buf.append(".").append(arg.toString());
        }
    }
}

4:PO类

注:所有的javabean都继承po类
package com.fengyong.base.beans;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;

import java.io.Serializable;
import java.lang.reflect.Field;

/**
 * 类描述:
 *
 * @author fengyong
 * @version 1.0
 * @since 1.0
 * Created by fengyong on 16/7/29 上午11:28.
 */
public class Po extends BaseBean implements Serializable {
    private static final long serialVersionUID = 3741866100111444587L;

    /**
     * 拷贝对象
     * @param po
     * @param <T>
     * @return
     */
    public  <T extends Po> T fromPo(Po po) {
        BeanUtils.copyProperties(po, this);
        return (T)this;
    }
    /**
     * key的添加:属性值,引用类型判断null不添加,String判断null和""不添加
     * @return
     * @throws IllegalAccessException
     */
    public String cacheString() throws IllegalAccessException {
        return cacheString(null);
    }

    /**
     *
     * @param attachedKey   该参数用于避免偶尔相同的cacheKey
     * @return
     * @throws IllegalAccessException
     */
    public String cacheString(String attachedKey) throws IllegalAccessException {
        StringBuffer sb = new StringBuffer();
        if(StringUtils.isNotBlank(attachedKey))
            sb.append(".").append(attachedKey).append(".");
        sb.append(this.getClass().getSimpleName()).append("{");
        Field[] fields = this.getClass().getDeclaredFields();
        for(Field field:fields){
            field.setAccessible(true);
            if(field.get(this)!=null){
                if(field.get(this) instanceof String){
                    if((field.get(this))!=""){
                        sb.append(field.getName()).append("=");
                        sb.append(field.get(this)).append(",");
                    }
                }else{
                    sb.append(field.getName()).append("=");
                    sb.append(field.get(this)).append(",");
                }

            }
        }
        sb.deleteCharAt(sb.length()-1).append("}");
        return sb.toString();
    }
}

5:测试

1:被测试的service
@Cacheable(keyMode = Cacheable.KeyMode.CACHEKEY)
public ResultPoBean<BaseSysUserPo> getSysUserPo( Long  sysUserPoId,@CacheKey BaseSysUserPo userPo,String str)

2:测试Test类
@Autowired
    private UserService userService;

    @Test
    public void userServiceTest() throws LogicException {
        Map<String,String> map = new HashMap<String, String>();
        BaseSysUserPo baseSysUserPo = new BaseSysUserPo();
        baseSysUserPo.setEmail("qq@163.com");
        baseSysUserPo.setUserName("fengyongl");
        ResultPoBean<BaseSysUserPo> resultPoBean = userService.getSysUserPo(new Long(320),baseSysUserPo,"测试参数");
    }

3:测试结果,key的值
com.system.service.user.UserService.getSysUserPo.BaseSysUserPo{userName=fengyongl,email=qq@163.com}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值