大家好,我是程序员田螺。
今天给大家讲一个“神奇”的玩意儿,注解
。每当我们在敲代码的时候,按下@Data
,在lombok
插件帮助下,就把繁琐的get set
工作做得服服帖帖;而敲下 @Test
,也能很方便的右键菜单运行我们的单元测试程序 ...
注解是Java中最重要的,但是却最容易被人遗忘的知识点。很多时候,就理所当然的觉得它就一直是那样子的;哪怕Spring
、SpringMVC
、SpringBoot
等框架中充满了注解
,还是选择性地忽视它。很多时候,不明白它是怎么起作用的,甚至把它和注释混淆 ... 我们在工作中机械性地在Controller
上加 @RequestMapping
。
想彻底弄清楚注解吗?
通过本文,循序渐进的彻底搞明白注解。
为什么要有注解
如果早期用xml bean
来配置来管理过类对象的相信有很深的感触,到项目的开发后期,开发人员都不知道什么时候开始,发现xml
的维护越来越糟糕。
而使用注解,能够让配置与代码维持一个很好的平衡(不过份耦合也不过份松散),而且也能 提高我们代码的阅读性,比如我看到 @Test
注解,会很自然的知道这个注解是用来做测试功能的;
还有一个潜在优势,就是和注解和注释一样,它的位置信息就能表示它的作用域;
例如下边这个@Test
注解,我们一看就知道在 funUnit
来作用,而实际也是如此。
因为有自定义注解的存在,所以也能方便我们扩展配置与功能;
所以呢,为什么我们需要注解,就是基于几点为初衷:
- 让我们从繁琐的配置文件中抽离出来;
- 提高代码阅读性;
- 自定义注解能够方便我们扩展配置与功能;
注解的定义
引用维基百科的定义:
Java注解又称Java标注,是JDK5.0版本开始支持加入源代码的特殊语法 元数据 。
Java语言中的类、方法、变量、参数和包等都可以被标注。和Javadoc不同,Java标注可以通过反射获取标注内容。在编译器生成类文件时,标注可以被嵌入到字节码中。Java虚拟机可以保留标注内容,在运行时可以获取到标注内容。当然它也支持自定义Java标注。
连边的一句话定义:
在指定的位置上放上一个记号,然后在这个记号的里边,可以有这个记号自己的属性,然后规定一些规则。(如:在什么地方可以放这个标记,在什么时候可以获取到这个标记。)
暂时不理解这句话没事,我们先补充一些注解的基础知识。
注解的语法
注解分类
- 自定义注解:自己写的注解,如我之前那篇文章,自定义的
@UserSiteMail、@PayCode
注解; - JDK内置注解:如
@Override
检验方法重写,@Deprecated
标识方法过期等 - 还有第三方框架提供的注解:SpringMVC的
@Controller
注解语法
上边这段代码, 有两个元注解(注解的注解),它属于JDK内置注解
元注解
@Target
:加在注解上,限定该注解能放的位置。
@Retention
:用来规定注解的保留策略,就是在哪个阶段,我们需要保留我们定义的这些标记。
保留策略(图片来源网络)
完整语法示例
还记得前边连边定义的那句话吗?
在指定的位置上放上一个记号,然后在这个记号的里边,可以有这个记号自己的属性,然后规定一些规则。(如:在什么地方可以放这个标记,在什么时候可以获取到这个标记。)
嵌套到这个注解中来翻译一下:
我在各种支付方式的地方,放上一个记号,记号里设置自己的属性(alia、weixin、jingdong),在类或者接口上可以放这个记号(@Target(ElementType.TYPE) ),这个标记在运行时的时候获取到(@Retention(RetentionPolicy.RUNTIME) )。
注解的本质与原理
本质
注解本质是一个继承了Annotation
的特殊接口,这里可以通过class文件看出;
查看class文件方式(简单的写一下步骤,不清楚的可以google
):
- IDEA左上角打开File—Project Structure
- 在Project Settings — Modules 下找到我们的项目
- 点击右侧的Paths , 查看Output Path位置
- 复制路径,在我的电脑中粘贴路径即可找到对应文件夹
-
javap -v
粘贴class文件路径
查看上面payCode
注解class文件如下:
payCode class文件
美化一下:
原理
接口本质的具体实现类是Java 运行时
生成的动态代理类。而我们通过反射获取注解时,返回的是Java 运行时生成的动态代理对象$Proxy1
。通过代理对象调用自定义注解(接口)的方法,会最终调用AnnotationInvocationHandler
的invoke
方法。该方法会从memberValues
这个Map 中索引出对应的值。而memberValues
的来源是Java 常量池。
注解实战
这里贴上我上一篇文章(连边分享 | 优雅重构 if...else)里边的项目实战,利用注解,优雅的避免了冗长的 if..else...
最后
这篇文章到这里就接近尾声了,稍微总结下,
本文从
- 为什么要使用注解
- 注解的定义
- 注解的语法
- 注解的本质与原理
- 注解实战
以上5个部分来讲解了注解
,