我对Annotation的理解

1.Annotation的定义

Annotation是代码里的特殊标记,这些标记可以在编译、类加载、运行时被读取,并经行相关的处理。

2.Annotation的原理

Annotation是一个接口,程序可以通过反射来获取指定程序元素的Annotation对象,然后通过Annotation对象来取得注释里的元数据。java.lang.reflect.AnnotatedElement接口提供了查询Annotation的程序成员,这个接口被java.lang.Package、java.lang.Class实现,并间接地被Method类、Constructor类、java.lang.reflect的Field类实现。而annotation中的方法参数可以通过Method类、Constructor类的getParameterAnnotations()方法获得。比如,下面的代码使用了AnnotatedElement类的isAnnotationPresent()方法判断某个方法是否具有@Unstable annotation,

1 import java.lang.reflect.*;
2 
3 Class c = WhizzBangClass.class;                           
4 Method m = c.getMethod("whizzy", int.class, int.class);  
5 boolean unstable = m.isAnnotationPresent(Unstable.class);

3.常见Annotation

这里只简单理解一下,不详细讲述

3.1基本Annotation

(1)@Override:限定重写父类方法

(2)@Deprecated:标记已经过时

(3)@SuppressWarnings:抑制编译器警告

(4)@SafeVarargs:Java 7的“堆污染”警告

3.2JDK的元Annotation

元Annotation即Meta Annotation,它是被用来声明annotation类型的annotation

(1)@Retention

只能用来修饰一个Annotation定义,用于指定被修饰的Annotation可以保留多长时间

(2)@Target

只能用来修饰一个Annotation定义,用于指定被修饰的Annotation能用于修饰哪些程序单元

(3)@Documented

用于指定被修饰的Annotation可以被javadoc工具提取为文档。

(4)@Inherited

用于指定被修饰的Annotation具有继承性。

3.3 常见的Spring Annotation

(1)@Autowired

实现bean的自动装配。使用@Autowired注解必须有且仅有一个与之匹配的bean.

(2)@Resource

实现bean的自动装配。使用@Resource注解必须有且仅有一个与之匹配的bean.

(3)@Component

只用该注解可以直接定义Bean,无需再xml中定义,若是两种定义同时存在,xml中的定义会覆盖注解中的bean定义

4.自定义Annotation

4.1定义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.       

4. 2使用Annotation

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

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


4.3提取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.     }  

其中程序的主程序如下

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

运行结果如下




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值