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;
    }
}

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

相关文章

  • Spring之AOP详解(非原创)

    文章大纲 一、AOP介绍二、Spring的AOP实战三、AOP常用标签四、项目源码及参考资料下载五、参考文章 一、...

  • 面向切面编程AOP

    安卓 AOP 实战:面向切片编程 T-MVP

  • 架构师JavaEE高级知识点,符合您的口味,成就您的未来!

    SSM项目整合 Spring IOC AOP 底层原理与实战、Spring mvc 各大组件 实现原理与项目实战、...

  • AOP实战

    想用AOP做一个缓存。虽然看起来简单,但真正做完还是有些收获。 读操作不能每次都查询,所以需要缓存。先看下基础类 ...

  • 彻底征服 Spring AOP 之 实战篇

    接上一小节彻底征服 Spring AOP 之 理论篇 Spring AOP 实战 看了上面这么多的理论知识, 不知...

  • 基于Spring Boot+JPA,使用AOP打印请求日志功能

    用过Spring的朋友应该多多少少都知道AOP(即面向切面),本篇文章我们就来实战如何使用AOP打印请求日志功能!...

  • AOP实战-IOS

    一、AOP简介 AOP: Aspect Oriented Programming 面向切面编程。 OOP:Obje...

  • 注解aop实战

    场景 在一数据库里有几张表,需要在触发字段更新的时候记录下来操作人和更新字段前后的值。不依赖MQ和监听binlog...

  • AOP实战小案例

    AOP实战小案例 前言 AOP技术是指面向切面编程技术,主要用于在具有横切逻辑的场景中,将横切逻辑提取出来,形成独...

  • Spring AOP编程实战

    Spring框架的IOC功能之注解的方式 Spring框架的IOC之注解方式的快速入门 Spring框架中Bean...

网友评论

      本文标题:AOP实战

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