在开发Java程序,尤其是Java EE应用的时候,总是免不了与各种配置文件打交道。以Java EE中典型的S(pring)S(truts)H(ibernate)架构来说,Spring、Struts和Hibernate这三个框架都有自己的XML格式的配置文件。这些配置文件需要与Java源代码保存同步,否则的话就可能出现错误。而且这些错误有可能到了运行时刻才被发现。把同一份信息保存在两个地方,总是个坏的主意。理想的情况是在一个地方维护这些信息就好了。其它部分所需的信息则通过自动的方式来生成。JDK 5中引入了源代码中的注解(annotation)这一机制。注解使得Java源代码中不但可以包含功能性的实现代码,还可以添加元数据。注解的功能类似于代码中的注释,所不同的是注解不是提供代码功能的说明,而是实现程序功能的重要组成部分。Java注解已经在很多框架中得到了广泛的使用,用来简化程序中的配置。从某种角度来说,可以把注解看成是一个XML元素,该元素可以有不同的预定义的属性。而属性的值是可以在声明该元素的时候自行指定的。在代码中使用注解,就相当于把一部分元数据从XML文件移到了代码本身之中,在一个地方管理和维护。
1定义注解
使用元注解定义注解,元注解有四种:
@Target(ElementType.[type])
[type]={METHOD, FIELD, TYPE(类、接口、枚举声明), CONSTRUCTOR, LOCAL_VARIABLE, PARAMETER,ANNOTATION_TYPE,PACKAGE}
@Retention(RetentionPolicy.[policy]) [policy]={SOURCE, CLASS, RUNTIME(反射机制可读取)}
SOURCE代表的是这个Annotation类型的信息只会保留在程序源码里,源码如果经过了编译之后,Annotation的数据就会消失,并不会保留在编译好的.class文件里面。 ClASS的意思是这个Annotation类型的信息保留在程序源码里,同时也会保留在编译好的.class文件里面,在执行的时候,并不会把这一些信息加载到虚拟机(JVM)中去.注意一下,当你没有设定一个Annotation类型的Retention值时,系统默认值是CLASS. RUNTIME,表示在源码、编译好的.class文件中保留信息,在执行的时候会把这一些信息加载到JVM中去的. 只有当声明为RUNTIME的时候,才能够在运行时刻通过反射API来获取到注解的信息
@Inherited 表示允许子类继承父类的注解
@Documented 表示将此注解包含到Javadoc中
注解中不能定义方法只能定义属性
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Name {
String firstname();
String lastname();
}
Annotation注解中的元素只能是下面的数据类型:
(1).java的8中基本类型,如int, boolean等等,如果可以自动装箱和拆箱,则可以使用对应的对象包装类型。
(2).String类型。
(3).Class类型。
(4).Enums类型。
(5).Annotation类型。
(6).上面类型的数组。
2使用注解
3通过反射机制获取注解元素的值: Method.getAnnotation(), Field.getDeclaredAnnotations()等方法
JDK 5中提供了apt工具用来对注解进行处理。apt是一个命令行工具,与之配套的还有一套用来描述程序语义结构的Mirror API。Mirror API(com.sun.mirror.*)描述的是程序在编译时刻的静态结构。通过Mirror API可以获取到被注解的Java类型元素的信息,从而提供相应的处理逻辑。具体的处理工作交给apt工具来完成。编写注解处理器的核心是AnnotationProcessorFactory和AnnotationProcessor两个接口。后者表示的是注解处理器,而前者则是为某些注解类型创建注解处理器的工厂。