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系统上, ...
随机推荐
- 【scratch3.0教程】1.3 了解scratch界面内容
第3课 了解Scratch界面内容 1.认识Scratch界面 双击桌面快捷方式,启动Scratch程序.我们来认识一下Scratch界面吧! (1)指令区 Scratch程序一共有运动.外观.声音. ...
- tomcat配置外部静态资源映射路径(windows和Linux部署)
如果你不想用ngnix配置的话,只单独使用tomcat的话可以看看这篇文章,接下来开始 使用场景 1.单机开发有时侯如果放在war下每次clean都会清理当前项目下静态文件特别折腾. 2.只有启动to ...
- Java泛型 - 返回父类的子类
一.栗子 public class GenericityInher { //error: Type mismatch: cannot convert from ArrayList<Child&g ...
- bootstrap table 列表增加输入框并保存输入的值不清除
需求: 在bootstrap table上增加输入框,需要选择的时候把输入的值保存到 row 里面,传递给其他模块使用. 实现: columns: [{ ...., { field: 'myField ...
- VisualStudio 连接 MySql 实现增删查改
首先创建数据库,建立一个用户登录表 2.visualStudio默认是不支持MySql的,要想通过Ado.Net 操作MySql 需要在管理NeGet包添加对MySql.Data 和 MySql.D ...
- Java Service Wrapper将jar包安装成Windows服务
刚接触java,第一次使用Java开发windows服务,也是刚不久看了SSM框架 简直也是一头雾水,不过只要用心理解,其实很简单,下面有详细的步骤,包学包会 在windows上运行jar包,需要在工 ...
- WebClient 请求 https 页面出错:未能创建 SSL/TLS 安全通道
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | Securi ...
- Js保存图片到本地
注:此方法是使用hbuilderx云打包之后才能用,否则在浏览器中会报 plus is not defined 官方文档 http://www.html5plus.org/doc/zh_cn/gall ...
- React 核心思想之声明式渲染
React 发展很快,概念也多,本文目的在于帮助初学者理清 React 核心概念. React 及 React 生态 React 的核心概念只有 2 点: 声明式渲染(Declarative) 基于组 ...
- 详解iOS的presentViewController(转)
一.用途和相关概念iOS中显示ViewController的方式有两种push和modal,modal也叫模态,模态显示VC是iOS的重要特性之一,其主要用于有以下场景: - 收集用户输入信息- 临时 ...