java注解原理及使用分享

177 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情

注解: 注解用来给类声明附加额外信息,可以标注在类、字段、方法等上面,编译器、JVM以及开发人员等都可以通过反射拿到注解信息,进而做一些相关处理。

元注解用来在声明新注解时指定新注解的一些特性

  1. @Target指定新注解标注的位置,比如类、字段、方法等,取值有ElementType.Method等
  2. @Retention指定新注解的信息保留到什么时候,取值有RetentionPolicy.RUNTIME等
  3. @Inherited指 定新注解标注在父类上时可被子类继承

可以做一个自定义限流注解的例子。

首先了解执行顺序:

  • 环绕通知开始
  • 前置通知
  • 目标方法执行
  • 环绕通知结束
  • 后置通知 这样我们在自定义注解时,就可以明白,限流的话,去限制目标方法执行,也就是在环绕通知中,去触发jionPoint.proceed();

如果环绕通知中执行了目标方法,则先执行前置通知,再执行目标方法。如果不执行目标方法,则不执行前置通知。

//每秒产生1个令牌,超过两次,则重试

//private RateLimiter rateLimiter = RateLimiter.create(1.0);

@RequestMapping("/get")
@MyLimit(name="get",token=1)
public String get(){
    /*boolean tryAcquire = rateLimiter.tryAcquire();
    if(!tryAcquire) return "当前访问人数过多";*/
    System.out.println("目标方法执行");
    return "my is get";
}
@Aspect
@Component
public class LimitApp {

    private ConcurrentHashMap<String, RateLimiter> rateLimiters = new ConcurrentHashMap<>();

    @Before(value = "@annotation(com.lijianb.jdk8.zj.MyLimit)")
    public void before(){
        System.out.println("---------------前置通知---------------");
    }



    @AfterReturning(value = "@annotation(com.lijianbing.jdk8.zj.MyLimit)")
    public void AfterReturning(){
        System.out.println("---------------后置通知---------------");
    }

    /**

     * 只有方法上加上MyLimit注解,才会被环绕通知

     * @param joinPoint

     * @return

     */

    @Around(value = "@annotation(com.lijianbing.jdk8.zj.MyLimit)")
    public Object around(ProceedingJoinPoint joinPoint){
        Signature signature = joinPoint.getSignature();
        //获取到拦截方法名
        MethodSignature methodSignature = (MethodSignature) signature;
        MyLimit declaredAnnotation = methodSignature.getMethod().getDeclaredAnnotation(MyLimit.class);
        //获取到该注解的name

        String name = declaredAnnotation.name();
        //获取到该注解的token
        double token = declaredAnnotation.token();



        RateLimiter rateLimiter = rateLimiters.get(name);
        //判断是否创建rateLimiters
        if(rateLimiter == null){
            rateLimiter = RateLimiter.create(token);
            rateLimiters.put(name,rateLimiter);
        }

        try {
            System.out.println("环绕通知开始");
            //执行目标方法  get()
            boolean tryAcquire = rateLimiter.tryAcquire();
            if (!tryAcquire) return "当前访问人数访问过多";
            Object proceed = joinPoint.proceed();
            System.out.println("环绕通知结束");
            return proceed;
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return "环绕通知";
    }
}

这样就做出了自定义注解。