Java 注解可以看做是 Javadoc 和 Xdoclet 標(biāo)簽的延伸和發(fā)展太闺,我們可以自定義注解標(biāo)簽蝴蜓,并通過 Java 語(yǔ)言的反射機(jī)制來(lái)獲取類中標(biāo)注的注解,完成特定的功能 。
注解是代碼的附屬信息咏尝,無(wú)論增加還是刪除注解,都不會(huì)影響程序代碼的運(yùn)行啸罢。因?yàn)?Java 語(yǔ)言解釋器會(huì)忽略這些注解编检,而讓第三方工具負(fù)責(zé)對(duì)注解進(jìn)行處理 。 第三方工具可以利用代碼中的注解間接控制程序代碼的運(yùn)行扰才,它們通過 Java 反射機(jī)制讀取注解的信息允懂,并根據(jù)這些信息更改邏輯 。
1 定義
我們使用 @interface
來(lái)定義注解類衩匣。
示例:
@Retention(RetentionPolicy.RUNTIME)//保留期限
@Target(ElementType.METHOD)//目標(biāo)類型
public @interface Log {
boolean value() default true;//聲明成員變量
}
示例中的 @Retention
與 @Target
被稱為元注解(Meta-annotation)蕾总。
1.1 成員變量
可以在注解類中定義多個(gè)成員變量,成員變量的定義語(yǔ)法有以下這些要求:
- 不能定義入?yún)ⅰ?/li>
- 不能拋出異常琅捏。
- 可以通過 default 定義一個(gè)默認(rèn)值生百。
- 合法的成員類型有這些 - 原始類型及其封裝類、Class柄延、enums蚀浆、注解類型和包含上述類型的數(shù)組類型。
- 如果注解類只有一個(gè)成員變量搜吧,那么必須名為
value()
市俊。在使用時(shí)可以忽略成員名稱和賦值符號(hào)(=
),比如可以這樣使用示例中的注解@Log(true)
滤奈。 - 如果注解類擁有多個(gè)成員變量摆昧,如果僅對(duì) value 進(jìn)行賦值,則也可以忽略成員名稱和賦值符號(hào)(
=
)蜒程。 - 如果注解類擁有多個(gè)成員變量绅你,又需要同時(shí)對(duì)多個(gè)成員變量進(jìn)行賦值,那么就必須使用成員名稱加賦值號(hào)表示搞糕,比如事務(wù)注解:
@Transactional(propagation= Propagation.MANDATORY,isolation= Isolation.DEFAULT)
勇吊。 - 注解類可以沒有成員變量,這樣注解類被稱為標(biāo)注注解窍仰,由調(diào)用程序負(fù)責(zé)判斷處理汉规。
- 注解類不能繼承其它類,也不能實(shí)現(xiàn)其它接口。
1.2 保留期限 @Retention
@Retention
表示保留期限针史,它被定義在 java.lang.annotation.RetentionPolicy 中:
保留期限類型 | 說明 |
---|---|
SOURCE | 注解信息僅保留在源代碼文件中晶伦。 |
CLASS | 注解信息保留在源代碼文件與字節(jié)碼文件中。 |
RUNTIME | 注解信息不僅保留在源代碼文件與字節(jié)碼文件中啄枕,而且會(huì)被加載到 JVM 中婚陪,在運(yùn)行期可以通過反射讀取這些注解信息。 |
1.3 目標(biāo)類型 @Target
@Target
表示注解的應(yīng)用目標(biāo)類型频祝。它被定義在 java.lang.annotation.ElementType 中泌参。
目標(biāo)類型 | 說明 |
---|---|
TYPE | 類、接口常空、注解類型沽一、Enum 處聲明。 |
FIELD | 成員變量漓糙、Enum 常量處聲明铣缠。 |
METHOD | 方法處聲明。 |
PARAMETER | 參數(shù)處聲明昆禽。 |
CONSTRUCTOR | 構(gòu)造函數(shù)處聲明蝗蛙。 |
LOCAL_VARIABLE | 局部變量處聲明。 |
ANNOTATION_TYPE | 注解類處聲明醉鳖。 |
PACKAGE | 包處聲明捡硅。 |
TYPE_PARAMETER | 類型參數(shù)處聲明。(1.8 新增) |
TYPE_USE | 使用類型處聲明辐棒。(1.8 新增) |
2 配置注解
public class User {
@Log()
public void rent(String userId) {
System.out.println("User:租賃【充電寶】");
}
@Log(false)
public void back(String userId){
System.out.println("User:歸還【充電寶】");
}
}
這里直接在需要的方法上病曾,加入注解類。
標(biāo)注注解的格式為:
@<注解名>(<成員名1>=<成員值1>,<成員名2>=<成員值2>,...)
如果成員變量是數(shù)組類型漾根,就可以通過{}
進(jìn)行賦值。
說明 | 示例 |
---|---|
單成員注解 | @Service("userService") |
多成員注解 | @Transactional(propagation= Propagation.MANDATORY,isolation= Isolation.DEFAULT) |
無(wú)成員注解 | @Override |
成員類型為普通數(shù)組 | @SuppressWarnings(value={"unchecked", "rawtypes"}) |
成員類型為注解數(shù)組 | @ComponentScans({@ComponentScan("1.xml"),@ComponentScan("2.xml")}) |
3 獲取注解
對(duì)于保留期限為 RetentionPolicy.RUNTIME
的注解鲫竞,可以通過反射來(lái)獲取注解信息 辐怕。
在 Java5.0 中, Package从绘、Class寄疏、Constructor、Method 以及 Field 等反射對(duì)象都新增了訪問注解的多種方法僵井,它們都支持泛型陕截。
Class clazz = User.class;
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
//獲取注解
Log log = method.getAnnotation(Log.class);
if (log != null) {
if (log.value()) {
System.out.println(method.getName() + "() 方法需要記錄日志");
} else {
System.out.println(method.getName() + "() 方法不需要記錄日志");
}
}
}
輸出結(jié)果:
back() 方法不需要記錄日志
rent() 方法需要記錄日志
是不是很簡(jiǎn)單呀 O(∩_∩)O哈哈~