Spring AOP实例

来源:互联网 发布:js offset什么意思 编辑:程序博客网 时间:2024/05/16 15:42

前面讲了理论部分,现在开始具体运用。
需求:通过在方法加@MyAnnotation自动实现,从缓存取,若没有就从别的地方取值,然后再入缓存。


  • 自定义注解MyAnnotation
/** * Created by King on 2017/8/30. */@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Inheritedpublic @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();        //type为null,则查询所有        list.add("执行Controller方法,为了测试22222222222");        return list;    }

  • 切面Aspect
@Aspect@Componentpublic 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();**

原创粉丝点击