Java語言解釋器會忽略註解,由第三方工具對註解進行處理。如使用Javadoc工具生成和源代碼配套的使用文檔。這些工具可以利用代碼中的註解信息來更改目標程序的邏輯。
通過定義一個自定義註解來標哪些業務方法需要測試,實例代碼如下:
1、定義註解類
/*
* 使用@interface修飾符定義註解類
*
* @Retention聲明註解的保留期限,有以下選擇值:
*
* (1)SOURCE 註解在字節碼中不保留
* (2)CLASS 進入目標類的字節碼文件中,但類加載器在加載字節碼文件時不會將註解加載到JVM,所以運行期間獲取不到
* (3)RUNTIME 在運行期間可通過反射獲取類中註解的信息
*
* Target 聲明使用該註解的目標類型
*
* (1)TYPE 類、接口、註解類、Enum聲明
* (2)FIELD 類成員變量或常量聲明
* (3)METHOD 方法聲明
* (4)PARAMETER 參數聲明
* (5)CONSTARUCTOR 構造函數
* (6)LOCAL_VARIABLE 局部變量
* (7)ANNOTATION_TYPE 註解類聲明
* (8)PACKAGE 包聲明
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface NeedTest {
/*
* 成員以無入參無拋出異常的方式聲明
* 可以通過default爲成員指定一個默認值,也可以不指定
* 成員類型是受限的,合法的類型包括原始類型及其封裝類(對象類型和List類型非法)
*
*/
boolean value() default false; // 只有一個成員方法時,名必須取爲value()
}
2、目標類
public class ForumService {
@NeedTest(true) // 可以省略成員名和賦值符號
public void deleteForum(int forumId) {
System.out.println("刪除論壇模塊:" + forumId);
}
@NeedTest(value = false)
public void deleteTopic(int topicId) {
System.out.println("刪除論壇主題:" + topicId);
}
}
3、測試類
public class TestTool {
public static void main(String[] args) {
Class clazz = ForumService.class;
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
NeedTest nt = method.getAnnotation(NeedTest.class); // Package、Method、Filed等反射對象都提供了訪問註解的方法
if (nt != null) {
if (nt.value()) {
System.out.println(method.getName() + "()需要測試");
} else {
System.out.println(method.getName() + "()不需要測試");
}
}
}
}
}
運行的結果如下:
deleteForum()需要測試
deleteTopic()不需要測試
下面來看一下相對複雜的例子,
註解類
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ValueBind {
enum fieldType {
STRING, INT
};
fieldType type();
String value();
}
目標類public class Student implements Serializable {
private String name = "";
public String getName() {
return name;
}
@ValueBind(type = fieldType.STRING, value = "aa")
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
@ValueBind(type = fieldType.INT, value = "30")
public void setAge(int age) {
this.age = age;
}
public String getStudentId() {
return studentId;
}
@ValueBind(type = fieldType.STRING, value = "101")
public void setStudentId(String studentId) {
this.studentId = studentId;
}
private int age = 0;
private String studentId = "";
}
測試類
public class PersistStudent {
public static void main(String[] args) throws Exception {
Object c = Class.forName("com.annotation.Student").newInstance();
try {
Method[] methodArray = c.getClass().getDeclaredMethods();
for (int i = 0; i < methodArray.length; i++) {
if (methodArray[i].isAnnotationPresent(ValueBind.class)) {
ValueBind annotation = methodArray[i].getAnnotation(ValueBind.class);
String type = String.valueOf(annotation.type());
String value = annotation.value();
if (type.equals("INT")) {
methodArray[i].invoke(c, new Integer[] { new Integer(value) });
} else {
methodArray[i].invoke(c, new String[] { value });
}
}
}
Student annotaedStudent = (Student) c;
System.out.println("studentId====" + annotaedStudent.getStudentId()
+ " studentnName====" + annotaedStudent.getName()
+ " student Age====" + annotaedStudent.getAge());
} catch (Exception e) {
throw new Exception(e);
}
}
}
運行的結果如下:studentId====101 studentnName====aa student Age====30
是不是非常像JPA的註解呀,其實他們的原理是一樣的。
參考文獻:
http://blog.csdn.net/lifetragedy/article/details/7394910