Java annotation源码解读

1、源码简介

Java annotation的源码主要在 java.lang.annotation包下面;

Java annotation源码解读


1.1 Annotation接口

不多说先上源码

/**
 * The common interface extended by all annotation types.  Note that an
 * interface that manually extends this one does <i>not</i> define
 * an annotation type.  Also note that this interface does not itself
 * define an annotation type.
 *
 * @author  Josh Bloch
 * @since   1.5
 */
/**
 * 首先声明英语不是很好,大致意思是:这是一个基础接口,所有的注解类型都继承与它。但是需要注意的是
 * (1)不需要手动指明一个注解类型是继承与它的(意思是自动继承)
 * (2)它本身不是注解类型
 */
public interface Annotation {
    /**
     * 这三个方法就不用多说了吧!
     */
    boolean equals(Object obj);
   
    int hashCode();

    String toString();

    /**
     * Returns the annotation type of this annotation.
     */
    /**
     * 返回注解的class
     */
    Class<? extends Annotation> annotationType();
}

真心觉得这个接口中没什么好说的!

1.2 ElementType和Target

@Target

限定Annotation所修饰的对象范围,范围包括packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标,一句话,这个Annotation可以用在什么地方。

可用的取值(ElementType)有:

    CONSTRUCTOR:用于描述构造器

    FIELD:      用于描述域

    LOCAL_VARIABLE:   用于描述局部变量

    METHOD:用于描述方法

    PACKAGE:用于描述包

    PARAMETER:用于描述参数

    TYPE:用于描述类、接口(包括注解类型) 或enum声明

/**
 * A program element type.  The constants of this enumerated type
 * provide a simple classification of the declared elements in a
 * Java program.
 *
 * <p>These constants are used with the {@link Target} meta-annotation type
 * to specify where it is legal to use an annotation type.
 *
 * @author  Joshua Bloch
 * @since 1.5
 */
public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    TYPE,

    /** Field declaration (includes enum constants) */
    FIELD,

    /** Method declaration */
    METHOD,

    /** Parameter declaration */
    PARAMETER,

    /** Constructor declaration */
    CONSTRUCTOR,

    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    ANNOTATION_TYPE,

    /** Package declaration */
    PACKAGE
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    RetentionPolicy value();
}

1.3 RetentionPolicy和Retention

这两个类表明了注解的生命周期;

SOURCE:在源文件中有效(即源文件保留)--出现在源代码中,而被编译器丢弃。

CLASS:在class文件中有效(即class保留)--被编译在class文件中;编译在class文件中的Annotation可能会被虚拟机忽略。

RUNTIME:在运行时有效(即运行时保留)--其被编译到class中,并在运行时,被读取和使用的。

/**
 * Annotation retention policy.  The constants of this enumerated type
 * describe the various policies for retaining annotations.  They are used
 * in conjunction with the {@link Retention} meta-annotation type to specify
 * how long annotations are to be retained.
 *
 * @author  Joshua Bloch
 * @since 1.5
 */
 /**
 * 指明注解的保留策略,和元注解Retention配合使用
 */
public enum RetentionPolicy {
   
    SOURCE,
  
    CLASS,

    RUNTIME
 /**
 * 是不是很熟悉,就是上面说道的,分别表示:
 * SOURCE:表明这个注解编译是就丢弃了,不会编译到class文件中;
 * CLASS:表明这个注解会被编译到Class文件中,但是在VM中运行时丢弃;
 * RUNTIME:这个是最常用的,表明注解会被保留到VM运行中; 
 */
}


/**
 * 这是基础的元注解,用于表示注解的保留策略
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    RetentionPolicy value();
}


1.4  Documented

描述其它类型的annotation被作为被标注的程序成员的公共API,从而被javadoc此类的工具文档化。

/**
 * Indicates that annotations with a type are to be documented by javadoc
 * and similar tools by default.  This type should be used to annotate the 
 * declarations of types whose annotations affect the use of annotated
 * elements by their clients.  If a type declaration is annotated with
 * Documented, its annotations become part of the public API
 * of the annotated elements.
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

1.5 Inherited

源代码很简单,但是我对这个继承标注真的弄得不是很清楚。以后在研究吧

指示注释类型被自动继承。如果在注释类型声明中存在 Inherited 元注释,并且用户在某一类声明中查询该注释类型,同时该类声明中没有此类型的注释,则将在该类的超类中自动查询该注释类型。此过程会重复进行,直到找到此类型的注释或到达了该类层次结构的顶层 (Object) 为止。如果没有超类具有该类型的注释,则查询将指示当前类没有这样的注释。

注意,如果使用注释类型注释类以外的任何事物,此元注释类型都是无效的。还要注意,此元注释仅促成从超类继承注释;对已实现接口的注释无效。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}

1.6 AnnotationFormatError、AnnotationTypeMismatchException、IncompleteAnnotationException

AnnotationFormatError:当注释分析器试图从类文件读取注释并确定注释出现异常时,抛出该错误。

AnnotationTypeMismatchException:若某个注释的类型在对该注释进行编译(或序列化)后发生了更改,而程序试图访问该注释的元素时,抛出此异常。

IncompleteAnnotationException:若某个注释在编译(或序列化)后将某个注释类型添加到其类型定义中,而程序试图该注释类型的元素时,抛出此异常。如果新元素有默认值,则不抛出此异常。

2、示例

(1)定义注解

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Description {
	String value();
}

(2)使用注解

@Description("Description say \"Hello Word\"")
public class Description_Test {
	
}

(3)实现注解

public class TestAnnotation {
	public static void main(String[] args) throws Exception {
		String CLASS_NAME = "com.shyann.jvm.annotation.Description_Test";
		Class<?> clz = Class.forName(CLASS_NAME);
		boolean flag = clz.isAnnotationPresent(Description.class);
		if (flag) {
			Description description = clz.getAnnotation(Description.class);
			System.out.println(description.value());
		}
	}
}

3、分析

个人觉得要分析的有两个方法isAnnotationPresent()和getAnnotation()

在Class类中找到了这两个方法

    public boolean isAnnotationPresent(
        Class<? extends Annotation> annotationClass) {
        if (annotationClass == null)
            throw new NullPointerException();

        return getAnnotation(annotationClass) != null;
    }

好吧原来弄到底还是只有getAnnotation()这一个方法啊

    public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
        if (annotationClass == null)
            throw new NullPointerException();

        initAnnotationsIfNecessary();//初始化
        return (A) annotations.get(annotationClass);
    }
//看了下这个方法。基本上就是扫描后放入到annotations中,完成初始话!
 private synchronized void initAnnotationsIfNecessary() {
        clearCachesOnClassRedefinition();//看了下这个方法,好像是清理缓存用的。
        if (annotations != null)
            return;
        declaredAnnotations = AnnotationParser.parseAnnotations(
            getRawAnnotations(), getConstantPool(), this);//这个方法没法找到啊
        Class<?> superClass = getSuperclass();
        if (superClass == null) {
            annotations = declaredAnnotations;
        } else {
            annotations = new HashMap<Class, Annotation>();
            superClass.initAnnotationsIfNecessary();
            for (Map.Entry<Class, Annotation> e : superClass.annotations.entrySet()) {
                Class annotationClass = e.getKey();
                if (AnnotationType.getInstance(annotationClass).isInherited())
                    annotations.put(annotationClass, e.getValue());
            }
            annotations.putAll(declaredAnnotations);
        }
    }

4、其实感觉只是很low的看了下源代码。真正核心的没有看到。以后能看到在看吧!

你可能感兴趣的:(Java annotation源码解读)