什么是注解

注解用来给类声明附加额外信息,可以标注在类、字段、方法等上面,编译器、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引进,此类型包括类型声明和类型参数声明

注解的Target

TYPE:类、接口(包括注解类型)和枚举的声明
FIELD:字段声明(包括枚举常量)
METHOD:方法声明
PARAMETER:参数声明
CONSTRUCTOR:构造函数声明
LOCAL_VARIABLE:本地变量声明
ANNOTATION_TYPE:注解类型声明
PACKAGE:包声明
TYPE_PARAMETER:类型参数声明,JavaSE8引进,可以应用于类的泛型声明之处
TYPE_USE:JavaSE8引进,此类型包括类型声明和类型参数声明

@Target(ElementType.METHOD)//当前注解放在哪里
@Retention(RetentionPolicy.RUNTIME)//注解的生命周期
@Inherited//当前注解继承
public @interface Zjname {
    
}
    public static void main(String[] args) throws NoSuchMethodException {
        UserEntity userEntity = new UserEntity();
        Class<? extends UserEntity> aClass = userEntity.getClass();
        Method setName = aClass.getDeclaredMethod("setName", String.class);
        //获取类上使用有使用Zjname 注解的注解
        Zjname annotation = setName.getAnnotation(Zjname.class);
        System.out.println(annotation);

    }

注解实现案例

自定义限流注解

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


@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface XlZJ {


    /**
     * 限流名称
     */
    String name() default "";

    /**
     *
     * @return  限流模式
     */
    double value() default 20;
}

@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.baomidou.springboot.common.XlZJ)")
    public Object around(ProceedingJoinPoint joinPoint) {
        try {
            //获取拦截的方法名
            Signature sig = joinPoint.getSignature();
            //获取拦截的方法名
            MethodSignature methodSignature = (MethodSignature) sig;
            // 判断方法上是否有加上该注解,如果有加上注解则限流
            XlZJ mayiktCurrentLimit =
                    methodSignature.getMethod().getDeclaredAnnotation(XlZJ.class);
            if (mayiktCurrentLimit == null) {
                // 执行目标方法
                return joinPoint.proceed();
            }
            // 获取注解上的name
            String name = mayiktCurrentLimit.name();
            // 获取注解上的token
            double token = mayiktCurrentLimit.value();
            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 "系统出现了错误!";
        }
    }
}

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