分类: 编程语言2013-03-18 01:06 3280人阅读 评论(6) 收藏 举报

上一篇文章已经介绍了如何使用JDK的三个标准Annotation,本文将介绍Annotation的原理,以及如何自定义Annotation,并利用Annotation来完成一些实际的功能。

定义Annotation

定义新的Annotation类型使用@interface关键字,这从一定意义上说明Annotation和接口的定义是有相似之处的。如下代码定义了一个Annotation

  1. //使用DK的元数据Annotation:Retention
  2. @Retention(RetentionPolicy.RUNTIME)
  3. //使用JDK的元数据Annotation:Target
  4. @Target(ElementType.METHOD)
  5. //定义一个标记注释,不包含任何成员变量,即不可传入元数据
  6. public @interface Testable{
  7. }

使用Annotation

定义了Annotation之后就可以在程序的任何地方使用该Annotation,对于Annotation的使用和public、final这样的修饰符很像,通常可以修饰类、方法、变量、接口等定义(默认情况下,Annotation用于修饰任何程序元素)。如下代码,就是使用了上面的Annotation修饰方法。

  1. public class MyTest {
  2. //使用@Testable标记注释指定该方法是可测试的
  3. @Testable
  4. public static void m1(){
  5. }
  6. public static void m2(){
  7. }
  8. //使用@Testable标记注释指定该方法是可测试的
  9. @Testable
  10. public static void m3(){
  11. throw new RuntimeException("Boom");
  12. }
  13. public static void m4(){
  14. }
  15. //使用@Testable标记注释指定该方法是可测试的
  16. @Testable
  17. public static void m5(){
  18. }
  19. public static void m6(){
  20. }
  21. //使用@Testable标记注释指定该方法是可测试的
  22. @Testable
  23. public static void m7(){
  24. throw new RuntimeException("Crash");
  25. }
  26. public static void m8(){
  27. }
  28. }

提取Annotation

一个类或者一个方法使用Annotation修饰之后需要通过反射来提取Annotation的信息。需要注意当一个Annotation类型被定义为运行时Annotation后该注释才是运行时可见的,当class文件被装载时被保存在class文件中的Annotation才会被虚拟机读取。下面代码就是将Annotation信息提取出来,根据这些信息进行相应的操作。在这里是如果某个方法被标记为可以测试的则调用这个方法。

  1. public class TestProcessor {
  2. public static void process(String clazz)throws ClassNotFoundException{
  3. int passed=0;
  4. int failed=0;
  5. //遍历obj对象的所有方法
  6. for(Method m :Class.forName(clazz).getMethods()){
  7. //如果包含@Testable标记注释
  8. if(m.isAnnotationPresent(Testable.class)){
  9. try{
  10. //调用m方法
  11. m.invoke(null);
  12. //passed加1
  13. passed++;
  14. }catch (Exception ex) {
  15. System.out.printf("方法"+m+"运行失败,异常"+ex.getCause()+"\n");
  16. failed++;
  17. }
  18. }
  19. }
  20. //统计测试结果
  21. System.out.println("共运行了:"+(passed+failed)+"个方法,其中:\n失败了:"+failed+",个,\n成功了:"+passed+"个!\n");
  22. }
  23. }

其中程序的主程序如下

  1. public class RunTests {
  2. public static void main(String[] args) throws Exception{
  3. //处理Mytest类
  4. TestProcessor.process("annotation.MyTest");
  5. }
  6. }

运行结果如下

工作原理

上面仅仅是一个简单地Annotation的使用,更复杂一些的Annotation与上面的这个例子原理是一样的,只不过相应的逻辑判断以及涉及到的Annotation中的内容较为复杂而已。但是核心的部分就是借助一个操作类通过反射的方式提取Annotation信息,进行操作,简而言之:无反射,不注释(Annotation)

Java中的Annotation(2)----Annotation工作原理的更多相关文章

  1. 浅谈Java中的System.gc()的工作原理

    很多人把Java的“效率低下”归咎于不能自由管理内存,但我们也知道将内存管理封装起来的好处,这里就不赘述. Java中的内存分配是随着new一个新的对象来实现的,这个很简单,而且也还是有一些可以“改进 ...

  2. 关于java中的hashcode和equals方法原理

    关于java中的hashcode和equals方法原理 1.介绍 java编程思想和很多资料都会对自定义javabean要求必须重写hashcode和equals方法,但并没有清晰给出为何重写此两个方 ...

  3. 【java】详解java中的注解(Annotation)

    目录结构: contents structure [+] 什么是注解 为什么要使用注解 基本语法 4种基本元注解 重复注解 使用注解 运行时处理的注解 编译时处理的注解 1.什么是注解 用一个词就可以 ...

  4. 【转载:java】详解java中的注解(Annotation)

    目录结构: contents structure [+] 什么是注解 为什么要使用注解 基本语法 4种基本元注解 重复注解 使用注解 运行时处理的注解 编译时处理的注解 1.什么是注解 用一个词就可以 ...

  5. 深入理解Java中的反射机制和使用原理!详细解析invoke方法的执行和使用

    反射的概念 反射: Refelection,反射是Java的特征之一,允许运行中的Java程序获取自身信息,并可以操作类或者对象的内部属性 通过反射,可以在运行时获得程序或者程序中的每一个类型的成员活 ...

  6. Java中的注解是如何工作的?

    自Java5.0版本引入注解之后,它就成为了Java平台中非常重要的一部分.开发过程中,我们也时常在应用代码中会看到诸如@Override,@Deprecated这样的注解.这篇文章中,我将向大家讲述 ...

  7. Java 线程池的介绍以及工作原理

    在什么情况下使用线程池? 1.单个任务处理的时间比较短 2.将需处理的任务的数量大 使用线程池的好处: 1. 降低资源消耗: 通过重复利用已创建的线程降低线程创建和销毁造成的消耗.2. 提高响应速度: ...

  8. Java web每天学之Servlet工作原理详情解析

    上篇文章中我们介绍了Servlet的实现方式以及Servlet的生命周期,我们这篇文章就来介绍一下常用对象. 点击回顾:<Java Web每天学之Servlet的工作原理解析>:<J ...

  9. JUC之Java中的阻塞队列及其实现原理

    在文章线程池实现原理 - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com)中介绍了线程池的组成部分,其中一个组成部分就是阻塞队列.那么JAVA中的阻塞队列如何实现的呢? 阻塞队列,关键字是阻塞 ...

  10. Java并发--Java中的CAS操作和实现原理

    版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/CringKong/article/deta ...

随机推荐

  1. MySql表中key的区别

    我们看到Key那一栏,可能会有4种值,即'啥也没有','PRI','UNI','MUL'1. 如果Key是空的, 那么该列值的可以重复, 表示该列没有索引, 或者是一个非唯一的复合索引的非前导列2. ...

  2. MySQL基础之第11章 插入、更新与删除数据

    11.1.插入数据 11.1.1.为表的所有字段插入数据 1.INSERT语句中不指定具体的字段名         insert into 表名 values (值1,值2…值n)2.INSERT语句 ...

  3. MVC ActionResult -- JavaScriptResult,JsonResult

    以下是ActionResult的继承图: 大概的分类: EmptyResult:表示不执行任何操作的结果 ContentResult :返回文本结果 JavaScriptResult:返回结果为Jav ...

  4. Ch04-文字列表的设计

    Ch04: 文字列表的设计 4.1 编号列表 语法: <OL> <li>编号1 <li>编号2 ...... </OL> 属性: 编号类型:type=1 ...

  5. innodb buffer pool

    add page to flush list buffer pool中的page,有三种状态: l  free:      当前page未被使用 l  clean:    当前page被使用,对应于数 ...

  6. [Everyday Mathematics]20150203

    设 $f$ 在 $\bbR$ 上连续可导, 且 $\dps{f'\sex{\frac{1}{2}}=0}$. 试证: $$\bex \exists\ \xi\in \sex{0,\frac{1}{2} ...

  7. ajax-Ajax试题

    ylbtech-doc:ajax-Ajax试题 Ajax 1.A,Ajax试题返回顶部 001.{Ajax题目}使用Ajax可带来便捷有()(选择3项)      A)减轻服务器的负担      B) ...

  8. history命令

    在 Linux 下面可以使用 history 命令查看用户的所有历史操作,同时 shell 命令操作记录默认保存在用户目录的 .bash_history 文件中.通过这个文件可以查询 shell 命令 ...

  9. 翻译【ElasticSearch Server】第一章:开始使用ElasticSearch集群(4)

    停止ElasticSearch(Shutting down ElasticSearch) 尽管我们期望集群(或节点)终生完美运行,我们最终可能需要重启或者正确的停止它(例如,维护).有三种方式来停止E ...

  10. codeforces 675C Money Transfers map

    上面是官方题解,写的很好,然后就A了,就是找到前缀和相等的最多区间,这样就可以减去更多的1 然后肯定很多人肯定很奇怪为什么从1开始数,其实从2开始也一样,因为是个环,从哪里开始记录前缀和都一样 我们的 ...