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

java annotation(注解)--入门

2010-09-27 15:02 351 查看
学习java的人都知道java中有javadoc这样的java注解,这类注解是用来生成帮助文档用的。

在EJB、Spring、Hibernate、Struts现都可用注解方式配置应用,但是我们对java annotation又有多少了解呢

其实annotation说是元数据(元数据大家应该不陌生--元数据
最本质、最抽象的定义为:

data about data (关于数据的数据--

关于数据的数据或者叫做用来描述数据的数据

)

元数据的作用

如果要对于元数据的作用进行分类,目前还没有明确的定义,不过我们可以根据它所起的作用,大致可分为三类:
l

编写文档:通过代码里标识的元数据生成文档。
l

代码分析:通过代码里标识的元数据对代码进行分析。
l

编译检查:通过代码里标识的元数据让编译器能实现基本的编译检查。

先看看怎么定义一个annotation

public @interface TestMethodAnnotation {

}

就是在定义接口的interface前加@
再看使用方法


@TestMethodAnnotation
public String getName() {
return name;
}


添加变量

public @interface TestMethodAnnotation {
boolean serialize() default true;

}



@TestMethodAnnotation(serialize = false)
public String getName() {
return name;
}



为变量赋默认值

public @interface TestMethodAnnotation {
boolean serialize() default true;

}


限定注释使用范围

当我们的自定义注释不断的增多也比较复杂时,就会导致有些开发人员使用错误,主要表现在不该使用该注释的地方使用。为此,Java

提供了一个ElementType

枚举类型来控制每个注释的使用范围,比如说某些注释只能用于普通方法,而不能用于构造函数等。下面是Java

定义的ElementType

枚举:
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
}


添加使用范围
@Target(ElementType.METHOD)
public @interface TestMethodAnnotation { boolean serialize() default true; }


这样表明该annotation只能用于方法注解

注释保持性策略

public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time.  This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}



CLASS


编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释。即要通过java反射得到它是得不到的
RUNTIME


编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。
SOURCE


编译器要丢弃的注释。即要通过java反射得到它是得不到的
使用策略;

注释保留策略。此枚举类型的常量描述保留注释的不同策略。它们与
Retention


元注释类型一起使用,以指定保留多长的注释。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestMethodAnnotation { boolean serialize() default true; }



运行时注解的读取

类类型注解
TestBean testbean = new TestBean();

Class clazz = testbean.getClass();
TestClassAnnotation testClassAnnotation = (TestClassAnnotation) clazz
.getAnnotation(TestClassAnnotation.class);


方法类型注解
Method readMethod = prop.getReadMethod();
System.out.print(",readMethod:" + readMethod.getName());
。。。。。。。。。。。。。。。
TestMethodAnnotation testAnnotation = readMethod
.getAnnotation(TestMethodAnnotation.class);
if (testAnnotation != null) {
System.out.println("serialize:"
+ testAnnotation.serialize());
}


以下为完整的测试用例:
只能用于方法类型
package com.parkingfo.test.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestMethodAnnotation { boolean serialize() default true; }


只能用于类类型
package com.parkingfo.test.annotation;
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)
public @interface TestClassAnnotation {
String descript();
}


使用
package com.parkingfo.test;
import com.parkingfo.test.annotation.TestClassAnnotation;
import com.parkingfo.test.annotation.TestMethodAnnotation;
@TestClassAnnotation(descript = "这是测试描述")
public class TestBean extends Object {
private String name;
@TestMethodAnnotation(serialize = false)
public String getName() {
return name;
}
/**
* @param name
*/
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return super.toString();
}

}


测试类
package com.parkingfo.test;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import com.parkingfo.test.annotation.TestClassAnnotation;
import com.parkingfo.test.annotation.TestMethodAnnotation;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
TestBean testbean = new TestBean();

Class clazz = testbean.getClass();
TestClassAnnotation testClassAnnotation = (TestClassAnnotation) clazz
.getAnnotation(TestClassAnnotation.class);

System.out.println(testClassAnnotation.descript());
BeanInfo beanInfo;
try {
beanInfo = Introspector.getBeanInfo(clazz);
PropertyDescriptor[] props = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor prop : props) {
String propName = prop.getName();
System.out.print("propterty:" + propName);
Method readMethod = prop.getReadMethod();
System.out.print(",readMethod:" + readMethod.getName());
Method writeMethod = prop.getWriteMethod();
if (writeMethod != null) {
System.out.print(",writeMethod:" + writeMethod.getName());
}
System.out.println();
TestMethodAnnotation testAnnotation = readMethod
.getAnnotation(TestMethodAnnotation.class);
if (testAnnotation != null) {
System.out.println("serialize:"
+ testAnnotation.serialize());
}
}
} catch (IntrospectionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}


测试类中用到了得到javabean信息的类Introspector的getBeanInfo(Class clazz)方法得到javabean的信息
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: