美文网首页
spring aop redis缓存实现

spring aop redis缓存实现

作者: wangpeng123 | 来源:发表于2018-04-25 17:46 被阅读0次

annotation:

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Cache {

    int expire() default 60;

    boolean sync() default false;
}

aspect:

package com.cache.aspect;

import com.cache.annotation.Cache;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import javax.annotation.PostConstruct;
import java.lang.reflect.Method;

/**
 * 切面执行逻辑
 * Created by wangpeng on 2018/3/6.
 */
@Component
@Aspect
public class CacheAnnotationAspect {
    private static Logger log = LoggerFactory.getLogger(CacheAnnotationAspect.class);
    private final Object syncLock = new Object();

    private JedisPool jedisPool;

    public CacheAnnotationAspect() {

    }

    @PostConstruct
    public void init() {
        jedisPool = new JedisPool("127.0.0.1");
    }

    /**
     * 切面匹配为class使用了@Service 或 @Component 并且方法使用了自定义的@Cache
     *
     * @param jp
     * @return
     * @throws Throwable
     */
    @Around("(@within(org.springframework.stereotype.Service)|| @within(org.springframework.stereotype.Component))&& @annotation(com.cache.annotation.Cache)")
    private Object cacheProcess(ProceedingJoinPoint jp) throws Throwable {
        Jedis jedis = jedisPool.getResource();
        Object[] args = jp.getArgs();
        if (args.length == 0) {
            return jp.proceed();
        } else {
            Signature sig = jp.getSignature();
            MethodSignature msig = null;
            if (!(sig instanceof MethodSignature)) {
                throw new IllegalArgumentException("该注解只能用于方法");
            }
            msig = (MethodSignature) sig;
            Object target = jp.getTarget();
            Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
            Cache cache = currentMethod.getAnnotation(Cache.class);
            if (jedis == null) {
                return jp.proceed(args);
            } else {
                Object rval = null;
                int expire = cache.expire();
                if (cache.sync()) {
                    synchronized (this.syncLock) {
                        rval = this.cacheInvoke(jedis, jp, args, expire);
                    }
                } else {
                    rval = this.cacheInvoke(jedis, jp, args, expire);
                }
                return rval;
            }
        }
    }


    /**
     * 执行缓存逻辑
     *
     * @param jp
     * @param args
     * @param expire
     * @return
     * @throws Throwable
     */
    private Object cacheInvoke(Jedis jedis, ProceedingJoinPoint jp, Object[] args, int expire) throws Throwable {
        String cacheKey = (String) args[0];
        log.debug("Load from cache for key : {}", args[0]);
        Object rval = jedis.get(cacheKey);//缓存中数据
        if (rval == null) {//缓存中没有,就要去数据库拿,拿完就放缓存
            log.info("Miss from cache, load backend for key : {}", cacheKey);
            rval = jp.proceed(args);//执行目标方法
            if (rval != null) {
                jedis.set(cacheKey, (String) rval);
                jedis.expire(cacheKey, expire);
            }
        }
        //test
        return rval;
    }
}

interface:

package com.cache.inter;

/**
 * Created by wangpeng on 2018/3/6.
 */
public interface UserService {
    String getAge(String id);
}

implements:

package com.cache.inter;

import com.cache.annotation.Cache;
import org.springframework.stereotype.Service;

/**
 * Created by wangpeng on 2018/3/6.
 */
@Service
public class UserServiceImpl implements UserService {


    @Cache(expire = 100)
    public String getAge(String id) {
        return "0";
    }
}

相关文章

网友评论

      本文标题:spring aop redis缓存实现

      本文链接:https://www.haomeiwen.com/subject/svkrqftx.html