您的位置:首页 > 编程语言 > Java开发

Java annotation源码解读

2015-03-17 10:01 363 查看
1、源码简介
Java annotation的源码主要在 java.lang.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的看了下源代码。真正核心的没有看到。以后能看到在看吧!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: