博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java annotation源码解读
阅读量:6672 次
发布时间:2019-06-25

本文共 6696 字,大约阅读时间需要 22 分钟。

  hot3.png

1、源码简介

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

233230_OuJ0_243998.png

1.1 Annotation接口

不多说先上源码

/** * The common interface extended by all annotation types.  Note that an * interface that manually extends this one does not 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
 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. * * 

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)@Documentedpublic @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
 annotationClass) {        if (annotationClass == null)            throw new NullPointerException();        return getAnnotation(annotationClass) != null;    }

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

    public 
 A getAnnotation(Class
 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
();            superClass.initAnnotationsIfNecessary();            for (Map.Entry
 e : superClass.annotations.entrySet()) {                Class annotationClass = e.getKey();                if (AnnotationType.getInstance(annotationClass).isInherited())                    annotations.put(annotationClass, e.getValue());            }            annotations.putAll(declaredAnnotations);        }    }

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

转载于:https://my.oschina.net/shyann/blog/387801

你可能感兴趣的文章