首页 > 代码库 > 1.2.4 Java Annotation 提要

1.2.4 Java Annotation 提要

(本文是介绍依赖注入容器Spring和分析JUnit源代码的准备知识)

Java Annotation(标注)

java.lang.annotation.Annotation是所有Java标注的父接口,它除了override/改写Object的equals(Object)、hashCode()和toString()外,仅有一个方法

Class<? extends Annotation> annotationType()

返回本标注的的类型。
JDK中定义的标注java.lang.Override为:
@Target(value=http://www.mamicode.com/METHOD)>再如java.lang. FunctionalInterface
@Documented
@Retention(value=http://www.mamicode.com/RUNTIME)>这些例子反映标注的一些基本内容:
①定义一个标注,如public @interface MyAnnotation,不需要extends Annotation而是使用@ interface。有一些用于修饰自定义标注的标注——称为元标注/meta-annotation,如Override例子中的@Target、@Retention和@Documented,其后是括号,括号中是使用逗号分割的名值对,(name=value)

@Target说明被修饰的标注的适用场合/目标。其值由枚举java.lang.annotation.ElementType限定,包括ANNOTATION_TYPE , CONSTRUCTOR , FIELD , LOCAL_VARIABLE , METHOD ,PACKAGE , PARAMETER , TYPE和TYPE_PARAMETER。例如Target自己的适用场合是@Target(value=http://www.mamicode.com/ANNOTATION_TYPE);如果标注只有单一属性成员(名值对),而并成员名为"value=http://www.mamicode.com/"可以省略为@Target(ANNOTATION_TYPE)。

@Retention说明被修饰的标注的保留策略,由RetentionPolicy枚举。

  • SOURCE只会保留在程序源码里,或者说仅对编译器有效,如@Override。编译器检查
  • 默认或指定CLASS时,指定该标注写入class文件,但是不会把这些信息加载到JVM中;
  • RUNTIME表示可以通过反射机制获得该标注。

@Documented指明该标注被反映在JavaDoc中。
②标注用来修饰源代码的元素(类,方法,属性,参数,本地变量,包,元标注)。
③标注的使用有一个明确的底线它们不可影响程序代码的执行。无论增加或删除标注,代码的执行不会有任何影响。但是,程序可以解析RUNTIME标注,并决定代码的行为

例子:JUnit4自定义的annotation

org.junit.Test

org.junit.Ignore @Target({ElementType.METHOD, ElementType.TYPE})

@Before和@After标示的方法只能各有一个,取代了JUnit以前版本中的setUp和tearDown方法

org.junit.BeforeClass @Target(ElementType.METHOD)

org.junit.Before @Target(ElementType.METHOD)

org.junit.AfterClass @Target(ElementType.METHOD)

org.junit.After @Target(ElementType.METHOD)

 

org.junit.runner.RunWith

org.junit.runners.Suite.SuiteClasses

org.junit.runners.Parameterized.Parameters


解析RUNTIME标注

①定义一个标注。
package MyTest;
import java.lang.annotation.*;
@Target(ElementType.METHOD)  
@Retention(RetentionPolicy.RUNTIME)  
public @interface MyAnnotation{
    String value();
}
②标注的使用类
package MyTest;
public class HelloWorld {
    @MyAnnotation("Test")
    public double add(double m,double n){
        return m+n;
    }
    @MyAnnotation("Ignore")
    public double add2(double m,double n){
        return m+n;
    }
}
③解析RetentionPolicy.RUNTIME标注。
通过c获得所有public方法,对每个方法获取其标注Annotation[],找到自定义的MyAnnotation,如果其value()的值为"Test",(Double)method.invoke(h,1,2.0);
package MyTest;
import java.lang.annotation.*;
import java.lang.reflect.*;
public class TestHelloWorld{    
    public static void main(String[] args)throws Exception{
        //直接使用反射机制
        Class<?> c = MyTest.HelloWorld.class;
        HelloWorld h =(HelloWorld)c.newInstance();
        Method[] methods = c.getMethods();
        for(Method method:methods){
            Annotation[] annotations = method.getDeclaredAnnotations();
            for(Annotation annotation : annotations){
                if(annotation instanceof MyAnnotation){
                    MyAnnotation myAnnotation = (MyAnnotation) annotation;
                    System.out.println("value: " + myAnnotation.value());
                    if(myAnnotation.value().equals("Test") ){
                        double d = (Double)method.invoke(h,1,2.0);
                        System.out.println(d);
                    }
                }
            }
        }
    }
}
输出:
value: Test
3.0
value: Ignore




1.2.4 Java Annotation 提要