注解

 

 

注解

注解概念

 

什么是注解

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

 

SpringBoot 全部都是采用注解化

常用注解

@Override     只能标注在子类覆盖父类的方法上面,有提示的作用

@Deprecated    标注在过时的方法或类上面,有提示的作用

@SuppressWarnings("unchecked")   标注在编译器认为有问题的类、方法等上面,用来取消编译器的警告提示,警告类型有serial、unchecked、unused、all

 

元注解

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

@Target 指定新注解标注的位置,比如类、字段、方法等,取值有ElementType.Method等

@Retention 指定新注解的信息保留到什么时候,取值有RetentionPolicy.RUNTIME等

@Inherited  指定新注解标注在父类上时可被子类继承

 

 

常用注解

@Target(ElementType.METHOD) // 指定新注解可以标注在方法上

@Retention(RetentionPolicy.RUNTIME) // 指定新注解保留到程序运行时期

@Inherited // 指定新注解标注在父类上时可被子类继承

public @interface MayiktName {

    public String name();

}

自定义注解 运行 :反射+aop

注解的Target

 

TYPE:类、接口(包括注解类型)和枚举的声明

FIELD:字段声明(包括枚举常量)

METHOD:方法声明

PARAMETER:参数声明

CONSTRUCTOR:构造函数声明

LOCAL_VARIABLE:本地变量声明

ANNOTATION_TYPE:注解类型声明

PACKAGE:包声明

TYPE_PARAMETER:类型参数声明,JavaSE8引进,可以应用于类的泛型声明之处

TYPE_USE:JavaSE8引进,此类型包括类型声明和类型参数声明

 

获取注解信息

         // 1.获取当前类上的注解
        Class<?> aClass = Class.forName("com.mayikt.entity.UserEntity");
//        MayiktName declaredAnnotation = aClass.getDeclaredAnnotation(MayiktName.class);
//        System.out.println(declaredAnnotation);
        // 2.获取当前方法上的注解
//        Method userNameMethod = aClass.getDeclaredMethod("getUserName");
//        MayiktName declaredAnnotation = userNameMethod.getDeclaredAnnotation(MayiktName.class);
//        System.out.println(declaredAnnotation);
        // 3.获取字段上的注解
        Field pubUserName = aClass.getDeclaredField("pubUserName");
        final MayiktName declaredAnnotation = pubUserName.getDeclaredAnnotation(MayiktName.class);
        System.out.println(declaredAnnotation);

        // 4.获得构造方法注解

        Constructor<TestAnnotation> constructors = clazz.getConstructor(new Class[] {});// 先获得构造方法对象

        MyConstructorAnnotation myConstructorAnnotation = constructors.getAnnotation(MyConstructorAnnotation.class);// 拿到构造方法上面的注解实例

        System.out.println(myConstructorAnnotation.desc() + "+" + myConstructorAnnotation.uri());

 

 

 

注解如何生效

实际项目中 注解想生效通过反射+aop机制

 

注解实现案例

自定义限流注解

 

对我们接口实现 限流 比如 每s 只能访问1次 或者每s 访问两次。

Maven


<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.1.RELEASE</version>
</parent>
<dependencies>
    <!--  springboot 整合web组件-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>18.0</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.12.0</version>
    </dependency>

</dependencies>

 

 

 

使用谷歌的guava例子

    /**
     * 每秒生成2.0个令牌
     * //
     */
//    private RateLimiter rateLimiter = RateLimiter.create(2.0);
    @GetMapping("/get")
//    @MayiktCurrentLimit(name = "get", token = 1)
    public String get() {
//        boolean result = rateLimiter.tryAcquire();
//        if (!result) {
//            return "当前访问人数过多,请稍后重试!";
//        }
        return "my is get";
    }

 

封装自定义注解限流框架

 

整合自定义注解

 

整合Aop实现接口限流

package com.mayikt.service.aop;

import com.google.common.util.concurrent.RateLimiter;
import com.mayikt.service.annotation.MayiktCurrentLimit;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 余胜军
 * @ClassName ExtTransactionalAop
 * @qq 644064779
 * @addres www.mayikt.com
 * 微信:yushengjun644
 */
@Aspect
@Component
public class CurrentLimitAop {
    /**
     * 每秒生成1.0个令牌 每s产生10 token
     */
//    private RateLimiter rateLimiter = RateLimiter.create(1);
    private ConcurrentHashMap<String, RateLimiter> rateLimiters = new ConcurrentHashMap();

    @Around(value = "@annotation(com.mayikt.service.annotation.MayiktCurrentLimit)")
    public Object around(ProceedingJoinPoint joinPoint) {
        try {
            //获取拦截的方法名
            Signature sig = joinPoint.getSignature();
            //获取拦截的方法名
            MethodSignature methodSignature = (MethodSignature) sig;
            // 判断方法上是否有加上该注解,如果有加上注解则限流
            MayiktCurrentLimit mayiktCurrentLimit =
                    methodSignature.getMethod().getDeclaredAnnotation(MayiktCurrentLimit.class);
            if (mayiktCurrentLimit == null) {
                // 执行目标方法
                return joinPoint.proceed();
            }
            // 获取注解上的name
            String name = mayiktCurrentLimit.name();
            // 获取注解上的token
            double token = mayiktCurrentLimit.token();
            RateLimiter rateLimiter = rateLimiters.get(name);
            if (rateLimiter == null) {
                rateLimiter = RateLimiter.create(token);
                rateLimiters.put(name, rateLimiter);
            }
            // 开始限流
            boolean result = rateLimiter.tryAcquire();
            if (!result) {
                return "当前访问人数过多,请稍后重试!";
            }
            return joinPoint.proceed();
        } catch (Throwable throwable) {
            return "系统出现了错误!";
        }
    }
}

 

 

使用效果
package com.mayikt.service;

import com.google.common.util.concurrent.RateLimiter;
import com.mayikt.service.annotation.MayiktCurrentLimit;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author
余胜军
 
* @ClassName MemberService
 * @qq 644064779
 * @addres www.mayikt.com
 *
微信:yushengjun644
 */
@RestController
public class MemberService {
    /**
     *
每秒生成2.0个令牌
    
* //
     */
//    private RateLimiter rateLimiter = RateLimiter.create(2.0);
   
@GetMapping("/get")
//    @MayiktCurrentLimit(name = "get", token = 1)
   
public String get() {
//        boolean result = rateLimiter.tryAcquire();
//        if (!result) {
//            return "
当前访问人数过多,请稍后重试!";
//        }
       
return "my is get";
    }

    @GetMapping("/add")
    @MayiktCurrentLimit(name = "add", token = 5)
    public String add() {
        return "my is add";
    }

    @GetMapping("/my")
    @MayiktCurrentLimit()
    public String my() {
        return "my is add";
    }
}

 

 

 

 

http://127.0.0.1:8080/get

http://127.0.0.1:8080/my

 

posted @ 2021-11-25 13:15  AngDH  阅读(119)  评论(0编辑  收藏  举报