AOP实战

作者: packet | 来源:发表于2019-03-06 21:28 被阅读0次

    想用AOP做一个缓存。虽然看起来简单,但真正做完还是有些收获。

    @RestController
    public class AccountController {
    
        @Autowired
        private AccountService accountService;
    
    
        @RequestMapping("/query")
        public long query(@RequestParam(required = false) String userId) {
            return accountService.queryMoney(userId);
        }
    
    }
    
    @Service
    public class AccountService {
    
        @Cache
        public long queryMoney(String userId) {
            try {
                System.out.println("start query money of " + userId);
                Thread.sleep(5000); // 模拟数据库查询
                long money = ThreadLocalRandom.current().nextLong(1000);
                System.out.println(userId + "->" + money);
                return money;
            } catch (Exception e) {
                e.printStackTrace();
                return -1;
            }
        }
    }
    

    读操作不能每次都查询,所以需要缓存。
    先看下基础类

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    @Documented
    public @interface Cache {
    }
    
    public class Money {
    
        private long num;
    
        private long ttl;
    
        public Money(long num, long ttl) {
            this.num = num;
            this.ttl = ttl;
        }
    
        public long getNum() {
            return num;
        }
    
        public void setNum(long num) {
            this.num = num;
        }
    
        public long getTtl() {
            return ttl;
        }
    
        public void setTtl(long ttl) {
            this.ttl = ttl;
        }
    }
    

    再看最重要的切面类:

    @Component
    @Aspect
    public class WorkAspect {
    
        private Map<String, Money> cache = new ConcurrentHashMap<>();
    
        @Pointcut("@annotation(com.example.aop.Cache)")
        public void point() {
        }
    
        @Around("point()")
        public long query(ProceedingJoinPoint joinPoint) {
            String userId = (String) joinPoint.getArgs()[0]; // 检查参数
            if (StringUtils.isEmpty(userId)) {
                return -1;
            }
            Money money = cache.get(userId);
            if (money != null && System.currentTimeMillis() < money.getTtl()) {
                return money.getNum();
            }
            long num = -1;
            try {
                num = (long) joinPoint.proceed();
                cache.put(userId, new Money(num, System.currentTimeMillis() + 60000));
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
            return num;
        }
    }
    

    这个业务背景需要注意,因为查询的是钱,所以要求当金钱数量变化的时候,缓存中的数据需要淘汰或者更新。

    相关文章

      网友评论

          本文标题:AOP实战

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