反射和注解
反射
反射技术的使用
Class类 代表类的实体,在运行的Java应用程序中表示类和接口
Field类 代表类的成员变量(成员变量也称为类的属性)
Method类 代表类的方法
Constructor类 代表类的构造方法
1.getField、getMethod和getCostructor方法可以获得指定名字的域、方法和构造器。
2.getFields、getMethods和getCostructors方法可以获得类提供的public域、方法和构造器数组,其中包括超类的共有成员。
3.getDeclatedFields、getDeclatedMethods和getDeclaredConstructors方法可以获得类中声明的全部域、方法和构造器,其中包括私有和受保护的成员,但不包括超类的成员。
获取Class文件的三种方式
Class.forName("类全名");
类名.class;
实例.getClass();
根据Class创建实例
.newInstance();//调用的是无参构造器
私有属性,开启访问呢权限
.setAccessible(true);
对方法的调用
.invoke();
反射可以直接越过泛型检查
泛型用在编译期,编译过后泛型擦除(消失掉),所以是可以通过反射越过泛型检查的
注意点:反射越过泛型检查存放其他类型数据后,使用lambda表达式遍历报类型转换异常。lambda表达式会根据泛型进行类型强转。
注解
什么是注解
注解用来给类声明附加额外信息,可以标注在类、字段、方法等上面,编译器、JVM以及开发人员等都可以通过反射拿到注解信息,进而做一些相关处理
常用注解
@Override 只能标注在子类覆盖父类的方法上面,有提示的作用
@Deprecated 标注在过时的方法或类上面,有提示的作用
@SuppressWarnings(“unchecked”) 标注在编译器认为有问题的类、方法等上面,用来取消编译器的警告提示,警告类型有serial、unchecked、unused、all
元注解
元注解用来在声明新注解时指定新注解的一些特性
@Target 指定新注解标注的位置,比如类、字段、方法等,取值有ElementType.Method等
@Retention 指定新注解的信息保留到什么时候,取值有RetentionPolicy.RUNTIME等
@Inherited 指定新注解标注在父类上时可被子类继承
元注解就是我们开发人员自己定义注解会使用到。
自定义注解 运行 : 反射+aop实现的
注解的Target
TYPE:类、接口(包括注解类型)和枚举的声明
FIELD:字段声明(包括枚举常量)
METHOD:方法声明
PARAMETER:参数声明
CONSTRUCTOR:构造函数声明
LOCAL_VARIABLE:本地变量声明
ANNOTATION_TYPE:注解类型声明
PACKAGE:包声明
TYPE_PARAMETER:类型参数声明,JavaSE8引进,可以应用于类的泛型声明之处
TYPE_USE:JavaSE8引进,此类型包括类型声明和类型参数声明
反射获取注解信息
.getDeclaredAnnotation
自定义限流注解(demo)
了解谷歌的限流框架的基本使用
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
/**
* 每秒生成2.0个令牌
*
*/
private RateLimiter rateLimiter = RateLimiter.create(2.0);
@GetMapping("/get")
public String get() {
boolean result = rateLimiter.tryAcquire();
if (!result) {
return "当前访问人数过多,请稍后重试!";
}
return "my is get";
}
封装限流注解的思路
1.需要自定义一个限流注解
每个请求方法限流规则不同
2.限流注解如何生效?
Spring Aop
环绕通知
1.先使用反射机制获取注解(查看是否有限流注解)
2.如果有该注解,调用限流api框架
@Aspect //标注在类上,标识切面类
@Around(value = "@annotation(注解的全类名)") public Object around(ProceedingJoinPoint joinPoint) { try { //获取拦截的方法名 Signature sig = joinPoint.getSignature(); //获取拦截的方法名 MethodSignature methodSignature = (MethodSignature) sig; // 判断方法上是否有加上该注解,如果有加上注解则限流 注解类 mayiktCurrentLimit = methodSignature.getMethod().getDeclaredAnnotation(注解类.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 "系统出现了错误!"; } }}
- 点赞
- 收藏
- 关注作者
评论(0)