持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情
注解: 注解用来给类声明附加额外信息,可以标注在类、字段、方法等上面,编译器、JVM以及开发人员等都可以通过反射拿到注解信息,进而做一些相关处理。
元注解用来在声明新注解时指定新注解的一些特性
- @Target指定新注解标注的位置,比如类、字段、方法等,取值有ElementType.Method等
- @Retention指定新注解的信息保留到什么时候,取值有RetentionPolicy.RUNTIME等
- @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 "环绕通知";
}
}
这样就做出了自定义注解。