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的看了下源代码。真正核心的没有看到。以后能看到在看吧!