分类: 编程语言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. 分析一下FastDFS_java_client中TestClient.java这个文件以及跟它关联的这条线

    本来先打算上个图来说明一下这条线的,可是我的画图工具还没有安装好,我先把跟TestClient.java相关的几个文件代码贴上来,但是由于代码行数还是不少的,所以请大家阅读文章的时候先不要展开代码,等 ...

  2. Darwin Streaming Server 安裝操作備忘

    Darwin Streaming Server 安裝操作 Darwin Streaming Server是蘋果公司推出的開放源碼.跨平台多媒體串流伺服器, 提供音樂 (mp3) 與影音 (3gp.mp ...

  3. TCP/IP详解学习笔记(11)-TCP交互数据流,成块数据流

    目前建立在TCP协议上的网络协议特别多,有telnet,ssh,有ftp,有http等等.这些协议又可以根据数据吞吐量来大致分成两大类:(1)交互数据类型,例如telnet,ssh,这种类型的协议在大 ...

  4. Java与WCF交互(一):Java客户端调用WCF服务

    最近开始了解WCF,写了个最简单的Helloworld,想通过java客户端实现通信.没想到以我的基础,居然花了整整两天(当然是工作以外的时间,呵呵),整个过程大费周折,特写下此文,以供有需要的朋友参 ...

  5. JAVA数据库处理(连接,数据查询,结果集返回)

    package john import java.io.IOException; import java.util.*; public class QueryDataRow { public Hash ...

  6. mbr grub的区别

    mbr是磁盘的物理扇区,不是程序名: 因为BIOS很小,功能有限,为了完成加载操作系统的功能,就产生了mbr: bios检测到一个硬盘后,将硬盘的0柱面.0磁头.1扇区的内容经过简单判断后, 至内存中 ...

  7. [转] c#中 多线程访问winform控件

    原文 c#中多线程访问winform控件的若干问题小结 我们在做winform应用的时候,大部分情况下都会碰到使用多线程控制界面上控件信息的问题.然而我们并不能用传统方法来解决这个问题,下面我将详细的 ...

  8. C# Adding Hyperlink to Windows Form z

    When creating a Windows form in C#, we would like to create a hyperlink so that when the user click ...

  9. lightoj 1021 (数位DP)

    题意:给你一个b进制的数,再给你一个十进制数k,你可以重新排列b进制数的每一位得到其他b进制数,问你这些数中有多少可以整除k? 思路:数位dp. #include <cstdio> #in ...

  10. LeetCode题解——Longest Common Prefix

    题目: 给定一系列的字符串,找出这些字符串的最长公共前缀. 解法: 暴力法,依次比较每个字符串的每个字符,碰到第一个不同的就返回之前找到的前缀. 代码: class Solution { public ...