Java获取类方法上的注解
Java获取类上的注解有下面3个方法:
- Class.getAnnotations() 获取所有的注解,包括自己声明的以及继承的
- Class.getAnnotation(Class< A > annotationClass) 获取指定的注解,该注解可以是自己声明的,也可以是继承的
- Class.getDeclaredAnnotations() 获取自己声明的注解
- 注解只有标注了@Inherited才能被子类继承
- 当某个类没有标注任何注解时,getAnnotations()和getDeclaredAnnotations()返回空数组
- 当某个注解查询不到时,getAnnotation(Class< A > annotationType)方法返回null
- 子类重写的方法,注解无法被继承,针对方法而言,getAnnotations()与getDeclaredAnnotations()返回的结果似乎永远都是一样的。
正常情况下,我们的class是 com
.cxytiandi.eureka_client.controller.ArticleController这种形式,如果用了AOP后,那么就会变成 com
.cxytiandi.eureka_client.controller.ArticleController$$EnhancerBySpringCGLIB$$3323dd1e这样了。
解决方案一
这种情况下拿到的Method也是被代理了的,所以Method上的注解自然获取不到,既然知道原因了,最简单快速的解决方法就是将多余的内容截取掉,然后重新得到一个没有被代理的Class对象,通过这个Class对象来获取Method,这样就可以获取到Method上的注解。
Class<?> clz = bean.getClass();
String fullName = clz.getName();
if (fullName.contains("EnhancerBySpringCGLIB") || fullName.contains("$$")) {
fullName = fullName.substring(0, fullName.indexOf("$$"));
try {
clz = Class.forName(fullName);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
Method[] methods = clz.getMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(Encrypt.class)) {
String uri = method.getAnnotation(Encrypt.class).value();
}
}
解决方案二
虽然问题解决了,但是还是觉得不够优雅,有没有更好的方式呢?我们可以用Spring里面提供的AnnotationUtils来读取注解。
Encrypt encrypt = AnnotationUtils.findAnnotation(method, Encrypt.class);
if (encrypt != null) {
String uri = encrypt.value();
}
AnnotationUtils.findAnnotation()原理是什么呢?为什么它可以获取到被代理后方法上的注解呢?
要想知道原理,那就只能看源码啦,源码多,不贴出来了,贴一点点关键的就行了
首先会构建一个AnnotationCacheKey,从本地缓存中获取,如果有的话直接返回,也就意味着只要读取过就会被缓存起来:
AnnotationCacheKey cacheKey = new AnnotationCacheKey(method, annotationType);
A result = (A) findAnnotationCache.get(cacheKey);
然后就是判断是否桥接方法,如果不是就直接返回,是的话则获取桥接方法的注解,如果还获取不到就通过接口来获取。
Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method);
result = findAnnotation((AnnotatedElement) resolvedMethod, annotationType);
if (result == null) {
result = searchOnInterfaces(method, annotationType, method.getDeclaringClass().getInterfaces());
}
后面就不继续下去了,最关键的代码其实是这句:
clazz = clazz.getSuperclass();
因为CGLIB代理会为目标类动态生成一个子类,所以我们要获取最原始的类,直接使用getSuperclass就可以了,跟第一种方案是一致的,只是第一种看起来有点那啥哈.....
推荐大家用AnnotationUtils去获取,这里面封装了很多的逻辑,考虑了很多场景下的问题,切莫重复造轮子。
Java获取类方法上的注解的更多相关文章
- AOP方法拦截获取参数上的注解
https://www.jianshu.com/p/f5c7417a75f9 获取参数注解 在spring aop中,无论是前置通知的参数JoinPoint,还是环绕通知的参数ProceedingJo ...
- Java获取Linux上指定文件夹下所有第一级子文件夹
说明:需要只获得第一级文件夹目录 package com.sunsheen.jfids.studio.monitor.utils; import java.io.BufferedReader; imp ...
- java获取当前上一周、上一月、上一年的时间
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Calendar c = Calend ...
- 黑马程序员——【Java高新技术】——JavaBean、注解
---------- android培训.java培训.期待与您交流! ---------- 一.JavaBean * 通过内省引入JavaBean:内省对应的英文全程是IntroSpector.在J ...
- 夯实Java基础(十七)——注解(Annotation)
1.注解概述 从JDK5.0开始,Java增加对元数据(MetaData)的支持,也就是注解(Annotation).其实我们早就已经接触过注解了,例如我们经常在Java代码中可以看到 “@Overr ...
- java反射之获取所有方法及其注解(包括实现的接口上的注解),获取各种标识符备忘
java反射之获取类或接口上的所有方法及其注解(包括实现的接口上的注解) /** * 获取类或接口上的所有方法及方法上的注解(包括方法实现上的注解以及接口上的注解),最完整的工具类,没有现成的工具类 ...
- spring aop获取目标对象的方法对象(包括方法上的注解)
这两天在学习权限控制模块.以前看过传智播客黎活明老师的巴巴运动网视频教程,里面就讲到权限控制的解决方案,当时也只是看看视频,没有动手实践,虽说看过几遍,可是对于系统中的权限控制还是很迷茫,所以借着这次 ...
- Spring:使用Spring AOP时,如何获取目标方法上的注解
当使用spring AOP时,判断目标方法上的注解进行相关操作,如缓存,认证权限等 自定义注解 package com.agent.annotation; import java.lang.annot ...
- linux下的shell命令的编写,以及java怎样调用linux的shell命令(java怎样获取linux上的网卡的ip信息)
程序猿都非常懒,你懂的! 近期在开发中,须要用到server的ip和mac信息.可是server是架设在linux系统上的,对于多网口,在获取ip时就产生了非常大的问题.以下是在windows系统上, ...
随机推荐
- js node md5模块使用问题
问题描述:md5(123456)得到的结果不是正确的. why? 问题查找: 1)安装路径问题: yarn add md5(md5模块在npmjs中显示每周download人数高达百万,有问题还这么多 ...
- [UOJ #167]【UR #11】元旦老人与汉诺塔
题目大意:给你一个有$n$个盘子的汉诺塔状态$S$,问有多少种不同的操作方法,使得可以在$m$步以内到达状态$T$.$n,m\leqslant100$ 题解:首先可以知道的是,一个状态最多可以转移到其 ...
- Synchronized 与Lock的不同之处
Synchronized 与Lock的不同之处 用法不一样.synchronized既可以加在方法上,也可以加载特定的代码块上,括号中表示需要锁的对象.而Lock需要显示地指定起始位置和终止位置.sy ...
- web项目服务器安装及配置(虚拟机centOS7)
一.安装VMware(如需) 1.首先下载VMware虚拟机,地址: https://www.vmware.com/products/workstation-pro/workstation-pro-e ...
- 原生JS-----一个剪刀石头布游戏
html: <h1>这是一个剪刀石头布游戏</h1> <h2>请出拳吧!少年!</h2> <h3>您已经获胜了<span id=&qu ...
- object-c 连接mysql
1. 通读 'mysql的使用' 2. 在Target->build setting 修改配置 User Header Search Paths 加入 /usr/local/mysql/incl ...
- js 数组 数组 最大值、最小值 算法(转载)
一:https://www.cnblogs.com/zhouyangla/p/8482010.html 1.排序法 首先我们给数组进行排序,可以按照从小到大的顺序来排,排序之后的数组中第一个和最后一个 ...
- python(if判断)
一.if判断 如果 条件满足,才能做某件事情, 如果 条件不满足,就做另外一件事情,或者什么也不做 注意: 代码的缩进为一个 tab 键,或者 4 个空格 在 Python 开发中,Tab 和空格不要 ...
- django--模型字段引用
如果内置字段不起作用,您可以尝试使用django-localflavor(文档),其中包含对特定国家和文化有用的各种代码片段. 此外,您可以轻松编写自己的自定义模型字段. 注意 从技术上讲,这些模型是 ...
- urllib模块中parse函数中的urlencode和quote_plus方法
本来只是向看一下quote_plus的作用,然后发现urlencode方法也是很方便的一个组合字符串的方法首先是介绍一下urlencode,他是将一些传入的元素使用&串联起来,效果如下: &g ...