反射和自定义注解实战案例

Posted zhixuChen200

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了反射和自定义注解实战案例相关的知识,希望对你有一定的参考价值。

反射和自定义注解实战案例


前言

写该文章的目的主要复习一些注解和反射的内容,同时也让大家理解一下框架中这两样技术是如何运用的。


提示:以下是本篇文章正文内容,下面案例可供参考

一、反射API

  • Class类:代表类的实体,在运行的Java应用程序中表示类和接口
  • Field类:代表类的成员变量(成员变量也称为类的属性)
  • Method类:代表类的方法
  • Constructor类:代表类的构造方法
  1. getField、getMethod和getCostructor方法可以获得指定名字的域、方法和构造器。
  2. getFields、getMethods和getCostructors方法可以获得类提供的public域、方法和构造器数组,其中包括超类的共有成员。
  3. getDeclatedFields、getDeclatedMethods和getDeclaredConstructors方法可以获得类中声明的全部域、方法和构造器,其中包括私有和受保护的成员,但不包括超类的成员。

二、接口限流实战案例

该实战案例是通过使用谷歌的guavay与自定义注解相结合来实现接口限流。

1导入依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>18.0</version>
        </dependency>
    </dependencies>

2.自定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CzxLimit 
    /**
     * name 限流的名称
     *
     * @return
     */
    String name() default "";

    /**
     * 每s 能够允许访问的次数 10 底层
     * 令牌桶
     *
     * @return
     */
    double token() default 10;

说明:

  1. token参数可以理解为该接口每秒最多可以访问几次。

3.定义控制层

@RestController
public class TestController 

    @GetMapping("/get")
    @CzxLimit(name = "get", token = 1)
    public String get() 
        return "get接口限制一秒钟登录一次";
    

    @GetMapping("/add")
    @CzxLimit(name = "add")
    public String add() 
        return "add接口限制一秒钟登录10次(不填默认10次)";
    

    @GetMapping("/push")
    public String push() 
        return "push接口无限制";
    

说明:

  1. 控制层我们定义了三个方法,并在get()和add()方法上加入了自定义注解,说明get()该接口每秒最对访问一次,add()上的自定义注解未填token属性的值,说明默认每秒访问10次。

4.使用AOP环绕通知拦截方法

注解和接口都已经定义好,我们来看看是怎么实现限流的。

@Aspect
@Component
public class CzxLimitAop 
    private ConcurrentHashMap<String, RateLimiter> rateLimiters = new ConcurrentHashMap<>();

    @Around(value = "@annotation(com.example.reflect.ano.CzxLimit)")
    public Object around(ProceedingJoinPoint joinPoint)
        try 
            //获取拦截的方法名
            Signature signature = joinPoint.getSignature();
            MethodSignature methodSignature = (MethodSignature) signature;
            //获取到该注解
            CzxLimit annotation = methodSignature.getMethod().getAnnotation(CzxLimit.class);
            String name = annotation.name();
            double token = annotation.token();
            // 判断该名称是否有创建RateLimiter
            RateLimiter rateLimiter = rateLimiters.get(name);
            if (rateLimiter == null) 
                rateLimiter = RateLimiter.create(token);
                rateLimiters.put(name, rateLimiter);
            
            rateLimiter.tryAcquire();
            //如果被限流的话
            boolean result = rateLimiter.tryAcquire();
            if (!result) 
                return "当前访问人数过多,请稍后重试!";
            
            Object proceedResult = joinPoint.proceed();// 目标方法   public String get() 
            return proceedResult;
        catch (Throwable throwable)
           return "系统错误";
        
    

说明

  1. @annotation(com.example.reflect.ano.CzxLimit)注解的作用是,该环绕通知会拦截所有加上了该注解的接口。
  2. 通过joinPoint获取拦截的方法进而获取该注解,再根据注解参数进行限流控制。

以上是关于反射和自定义注解实战案例的主要内容,如果未能解决你的问题,请参考以下文章

JavaWeb1.3.3基础加强:注解案例(注解+反射重构"JavaWeb-1.2.3基础加强:案例(反射+配置文件))

Java反射与自定义注解

JavaWeb之Java基础知识增强

JavaWeb之Java基础知识增强

JavaWeb之Java基础知识增强

java中 线程、注解、反射这几块知识在实战中用得到么?在何时会用到?