自定义annotation

Annotation的使用
@Target表示的是这个Annotation可以应用在哪里,是对Annotation应用的限制,如果没有这个标识的话,Annotation可以用在任何地方,比如类上,方法上,变量,属性上等,可以从java.lang.Enum.ElementType这个枚举里选择.

1.只能用在方法上的限制的应用

package com.test;   

import java.lang.annotation.ElementType;   
import java.lang.annotation.Target;   

@Target(ElementType.METHOD)   
public @interface TargetTest {   
String hello();   
}   

package com.test;   
public class TargetClass {   
@TargetTest(hello = "abc")   
public void doSomething()   
    {   
        System.out.println("do something");   
    }   
}

2.只能用于类上限制的应用

package com.test;     
import java.lang.annotation.ElementType;   
import java.lang.annotation.Target;   

@Target(ElementType.TYPE)   
public @interface TargetTest {   
    String hello();   
}   

package com.test;    
@TargetTest(hello = "abc")   
public class TargetClass {   
    public void doSomething()   
    {   
        System.out.println("do something");   
    }   
}
  • 注解@Retention可以用来修饰注解,是注解的注解,称为元注解.
  • Retention注解有一个属性value,是Retentionpolicy类型的,Enum RetentionPolicy是一个枚举值.
  • 这个枚举值决定了Retention注解应该如何去保持,也可理解Rentention搭配RententionPolicy使用.RetentionPolicy有三个值:CLASS RUNTIME SOURCE
  • 用@Retention(RetentionPolicy.CLASS)修饰的注解,表示注解的信息被保留在class文件(字节码文件)中,当程序编译时,但不会被虚拟机读取在运行的时候.
  • 用@Retention(RetentionPolicy.RUNTIME)修饰的注解,表示注解的信息被保留在class文件(字节码文件)中,当程序编译时,会被虚拟机保留在运行时.
  • 用@Retention(RetentionPolicy.SOURCE)修饰的注解,表示注解的信息会被编译器抛弃,不会留在class文件中,注解只会留在源文件中
  • RetentionPolicy.RUNTIME可以让你从JVM中读取Annotation注解的信息,以便在分析程序的时候使用.

下面实际操作一下:自己创建一个注解,用源注解为其注解.

@Retention(RetentionPolicy.RUNTIME)//用源注解修饰自定义的注解,可以从JVM读取该annotation.
public @interface MyAnnotation {

 String value() default "robin";//使用抽象方法,和普通接口一样,还可以定义默认值.
 String world();
 int[] array() default {2,4,5,6};
 Class style() default String.class;
 TargetTest hello() default @TargetTest(hello = "hahaha");//annotation也可以作为返回值返回.

}

下面就是正式使用自定义注解了

@MyAnnotation(value="robin",world="China",array={},style=int.class) //自定义annotation中的方法,可以为其赋上参数,  没有赋值就会使用默认的值
public class MyTest {
@MyAnnotation(hello=@TargetTest(hello="nihao"),world="America",array={1,2,3})
@Deprecated //被这个标签修饰的方法会出现过期的标记
public void output(){
 System.out.println("output something!");
}
}

下面就用到反射了,通过反射得到我们想要的东西

public class MyReflection {
 public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException,IllegalArgumentException, InvocationTargetException{
  MyTest myTest = new MyTest();
  Class<MyTest> c = MyTest.class; //得到Mytest类的信息
  Method method = c.getMethod("output", new Class[] {}); //指定方法的名称,new Class[]{里面指定参数的类型}如果是output(String,name,int num),那么就是这样("output",new Class[]{String.class,int.class})
  if(MyTest.class.isAnnotationPresent(MyAnnotation.class)){ //判断该类有没有使用MyAnnotattion的注解
   System.out.println("have annotation");

  }
  if(method.isAnnotationPresent(MyAnnotation.class)){ //判断该方法有没有使用MyAnnotattion的注解
  method.invoke(myTest, null);	 //调用方法的类,要传入的参数

  MyAnnotation myAnnotation=method.getAnnotation(MyAnnotation.class); //获取annotattion的实例
  String value=myAnnotation.value();
  String world=myAnnotation.world();
  System.out.println(value+","+world);
  System.out.println(myAnnotation.array().length);
  System.out.println(myAnnotation.hello().hello());
  System.out.println(myAnnotation.style());
  }

  Annotation[] annotations=method.getAnnotations();
  for(Annotation annotation:annotations){

   System.out.println(annotation.annotationType().getName());

  }

 }
}
posted @ 2016-02-22 21:34  It'sRobin  阅读(158)  评论(0编辑  收藏  举报