Annotation(注解)是什么?
附加在代碼中的一些元信息,用于一些工具在編譯、運行時進行解析和使用,起到說明、配置的功能。注解不會也不能影響代碼的實際邏輯,僅僅起到輔助性的作用。包含在 java.lang.annotation 包中。
1、Annotation的定義
首先看一下如何定義我們自己的注解,下面是SpringMvc中RequestParam注解的定義。@Retention(RetentionPolicy.RUNTIME) // 注解的保留策略
@Target(ElementType.PARAMETER) // 注解的作用目標
@Documented
public @interface RequestParam { // 使用@interface定義注解
String value() default ""; // 類似方法的屬性
boolean required() default true; // 使用default指定屬性的默認值
String defaultValue() default ValueConstants.DEFAULT_NONE;
}
@Target(ElementType.PARAMETER) // 注解的作用目標
@Documented
public @interface RequestParam { // 使用@interface定義注解
String value() default ""; // 類似方法的屬性
boolean required() default true; // 使用default指定屬性的默認值
String defaultValue() default ValueConstants.DEFAULT_NONE;
}
使用方式如下:
void deleteUser(@RequestParam(value="id",required=false) Long id) { }
2、元注解
元注解是指注解的注解。包括 @Retention @Target @Document @Inherited四種。2.1、@Retention: 定義注解的保留策略
@Retention(RetentionPolicy.SOURCE) 注解僅存在于源碼中,在class字節碼文件中不包含
@Retention(RetentionPolicy.CLASS) 默認的保留策略,注解會在class字節碼文件中存在,但運行時無法獲得,
@Retention(RetentionPolicy.RUNTIME) 注解會在class字節碼文件中存在,在運行時可以通過反射獲取到
2.2、@Target:定義注解的作用目標
@Target(ElementType.TYPE) 接口、類、枚舉、注解
@Target(ElementType.FIELD) 字段、枚舉的常量
@Target(ElementType.METHOD) 方法
@Target(ElementType.PARAMETER) 方法參數
@Target(ElementType.CONSTRUCTOR) 構造函數
@Target(ElementType.LOCAL_VARIABLE) 局部變量
@Target(ElementType.ANNOTATION_TYPE) 注解
@Target(ElementType.PACKAGE) 包
java.lang.Package
java.lang.Class
java.lang.reflect.Construtor
java.lang.reflect.Field
java.lang.reflect.Method
均實現了該接口,所以我們可以通過反射獲取到 Class、Construtor、Field、Mehtod等,然后再通過上述接口方法,獲得作用在這些元素上的注解。
下面是RequestParam注解的使用,為便于演示,略作修改,見org.springframework.web.bind.annotation.support.HandlerMethodInvoker源碼
@Deprecated: @Documented @Retention(RetentionPolicy.RUNTIME) 用于建議不要使用某元素
@SuppressWarnings:@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) @Retention(RetentionPolicy.SOURCE)
說明對被批注的代碼元 素內部的某些警告保持靜默
2.3、@Document:說明該注解將被包含在javadoc中
2.4、@Inherited:說明子類可以繼承父類中的該注解
3、通過反射讀取注解
package java.lang.reflect;
import java.lang.annotation.Annotation;
public interface AnnotatedElement {
/**判斷該元素中某個注解類型是否存在*/
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);
/**獲得該元素中某個注解類型的注解*/
<T extends Annotation> T getAnnotation(Class<T> annotationClass);
/**獲得該元素中所有可見的注解,包含繼承得到的注解*/
Annotation[] getAnnotations();
/**獲得該元素自身什么的注解,不包含繼承得到的注解*/
Annotation[] getDeclaredAnnotations();
}
import java.lang.annotation.Annotation;
public interface AnnotatedElement {
/**判斷該元素中某個注解類型是否存在*/
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);
/**獲得該元素中某個注解類型的注解*/
<T extends Annotation> T getAnnotation(Class<T> annotationClass);
/**獲得該元素中所有可見的注解,包含繼承得到的注解*/
Annotation[] getAnnotations();
/**獲得該元素自身什么的注解,不包含繼承得到的注解*/
Annotation[] getDeclaredAnnotations();
}
java.lang.Package
java.lang.Class
java.lang.reflect.Construtor
java.lang.reflect.Field
java.lang.reflect.Method
均實現了該接口,所以我們可以通過反射獲取到 Class、Construtor、Field、Mehtod等,然后再通過上述接口方法,獲得作用在這些元素上的注解。
下面是RequestParam注解的使用,為便于演示,略作修改,見org.springframework.web.bind.annotation.support.HandlerMethodInvoker源碼
Method handlerMethod = *****;
Annotation[] paramAnns = handlerMethod.getParameterAnnotations();
String paramName = null;
boolean required = false;
String defaultValue = null;
for (Annotation paramAnn : paramAnns) {
if (RequestParam.class.isInstance(paramAnn)) {
RequestParam requestParam = (RequestParam) paramAnn;
paramName = requestParam.value();
required = requestParam.required();
defaultValue = parseDefaultValueAttribute(requestParam.defaultValue());
annotationsFound++;
}
// *******其他處理*******************
}
Annotation[] paramAnns = handlerMethod.getParameterAnnotations();
String paramName = null;
boolean required = false;
String defaultValue = null;
for (Annotation paramAnn : paramAnns) {
if (RequestParam.class.isInstance(paramAnn)) {
RequestParam requestParam = (RequestParam) paramAnn;
paramName = requestParam.value();
required = requestParam.required();
defaultValue = parseDefaultValueAttribute(requestParam.defaultValue());
annotationsFound++;
}
// *******其他處理*******************
}
4、常見注解的說明及使用
@Override :@Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) 說明方法是對父類方法的覆蓋,用于編譯器編譯時進行檢查@Deprecated: @Documented @Retention(RetentionPolicy.RUNTIME) 用于建議不要使用某元素
@SuppressWarnings:@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) @Retention(RetentionPolicy.SOURCE)
說明對被批注的代碼元 素內部的某些警告保持靜默