前面讲了理论部分,现在开始具体运用。 需求:通过在方法加@MyAnnotation自动实现,从缓存取,若没有就从别的地方取值,然后再入缓存。
自定义注解MyAnnotation
/**
* Created by King on 2017/8/30.
*/
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @
interface MyAnnotation {
String key();
String hashKey();
ValueType valueType();
}
ValueType:是一个枚举类,定义了redis缓存的数据类型
目标方法
@MyAnnotation(key
="aaaaaaaaaaabbb",valueType
= ValueType
.Hash,hashKey
= "11111111")
public List<String> searchType11(
Integer a) {
List<String> list = Lists
.newArrayList();
list.add(
"执行Controller方法,为了测试22222222222");
return list;
}
切面Aspect
@Aspect
@Component
public class ShiliAspect {
private static final Logger logger = LoggerFactory.getLogger(ShiliAspect.class);
@Autowired
RedisTemplate redisTemplate;
@Pointcut(
"@annotation(com.cci.market.security.aop.MyAnnotation)")
public void save(){
}
@Around(
"save()")
public Object
addOperateLog(ProceedingJoinPoint pjp)
throws Throwable {
String methodName = pjp.getSignature().getName();
Method method = getMethod(pjp);
MyAnnotation cacheable = method.getAnnotation(MyAnnotation.class);
Object returnObj =
null;
if (cacheable.valueType().equals(ValueType.Map)){
Map<String, Object> map = redisTemplate.opsForHash().entries(cacheable.key());
if (map !=
null && map.size()>
0) {
map.put(
"AOP",
"这是从缓存去的");
map.put(
"cacheable.name()",cacheable.key());
return map;
}
}
else if (cacheable.valueType().equals(ValueType.Hash)){
returnObj = redisTemplate.opsForHash().get(cacheable.key(),cacheable.hashKey());
if (returnObj !=
null) {
return returnObj;
}
}
try{
returnObj = pjp.proceed(pjp.getArgs());
if (cacheable.valueType().equals(ValueType.Map)){
redisTemplate.opsForHash().putAll(cacheable.key(), (Map) returnObj);
}
else if (cacheable.valueType().equals(ValueType.Hash)){
redisTemplate.opsForHash().put(cacheable.key(),cacheable.hashKey(),returnObj);
}
redisTemplate.expire(cacheable.key(),
10, TimeUnit.SECONDS);
}
catch (Exception e){
logger.error(e.getMessage(),e);
}
return returnObj;
}
public static Method
getMethod(ProceedingJoinPoint pjp) {
Object[] args = pjp.getArgs();
Class[] argTypes =
new Class[pjp.getArgs().length];
for (
int i =
0; i < args.length; i++) {
if (args[i] !=
null) {
argTypes[i] = args[i].getClass();
}
}
Method method =
null;
try {
method = pjp.getTarget().getClass().getMethod(pjp.getSignature().getName(), argTypes);
}
catch (NoSuchMethodException e) {
e.printStackTrace();
}
catch (SecurityException e) {
e.printStackTrace();
}
return method;
}
}
改进:如果目标方法参数类型是int,long等,通过上述方法获取参数类型,直接变成了相应封装类。再根据方法名和参数类型去获取目标方法,会找不到。 其实获取目标方法有更加简单方法: **//获取目标方法 Method method = ((MethodSignature) pjp.getSignature()).getMethod();**