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";
}
}
网友评论