我們在使用Spring框架的時候,會經常使用類似:@Autowired 這樣的註解。我們也可以自己定義一些註解。Java的註解主要在包:java.lang.annotation中實現。
1. 元註解
什麼是元註解?你可以這樣理解,元註解是自定義註解的註解。元註解主要包含4個。他們主要在java.lang.annotation中可以找到。我們自己要創建註解的時候必須要用到這些元註解。所以必須徹底理解這四個元註解的含義。
1. @Documented
2. @Inherited
3. @Retention
4. @Target
例如:
- package com.test.www;
- import java.lang.annotation.Documented;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Inherited;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- /**
- * 定義一個用戶名的自定義註解
- * @author zhuli
- * @date 2014-7-5
- */
- @Documented
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ ElementType.TYPE, ElementType.METHOD})
- @Inherited
- public @interface UserNameAnnotations {
- public String value() default "";
- }
package com.test.www;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 定義一個用戶名的自定義註解
* @author zhuli
* @date 2014-7-5
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD})
@Inherited
public @interface UserNameAnnotations {
public String value() default "";
}
1. @Documented
@Documented用於描述其它類型的annotation應該被作爲被標註的程序成員的公共API,因此可以被例如javadoc此類的工具文檔化。Documented是一個標記註解,沒有成員。
2. @Inherited
@Inherited 元註解是一個標記註解,@Inherited闡述了某個被標註的類型是被繼承的。如果一個使用了@Inherited修飾的annotation類型被用於一個class,則這個annotation將被用於該class的子類。
3. @Target
@Target說明了Annotation所修飾的對象範圍:Annotation可被用於 packages、types(類、接口、枚舉、Annotation類型)、類型成員(方法、構造方法、成員變量、枚舉值)、方法參數和本地變量(如循環變量、catch參數)。
ElementType.CONSTRUCTOR 作用於構造器
ElementType.FIELD 作用於域/屬性
ElementType.LOCAL_VARIABLE 用於描述局部變量
ElementType.METHOD 作用於方法
ElementType.PACKAGE 用於描述包
ElementType.PARAMETER 用於描述參數
ElementType.TYPE 用於描述類、接口(包括註解類型) 或enum聲明,最常用
單個修飾對象的範圍:
- @Target(ElementType.TYPE)
@Target(ElementType.TYPE)
多個:
- @Target({ ElementType.TYPE, ElementType.METHOD})
@Target({ ElementType.TYPE, ElementType.METHOD})
4. Retention
定義了該Annotation被保留的時間長短:某些Annotation僅出現在源代碼中,而被編譯器丟棄;而另一些卻被編譯在class文件中;編譯在class文件中的Annotation可能會被虛擬機忽略,而另一些在class被裝載時將被讀取(請注意並不影響class的執行,因爲Annotation與class在使用上是被分離的)。使用這個meta-Annotation可以對 Annotation的“生命週期”限制。
RetentionPolicy.RUNTIME 註解會在class字節碼文件中存在,在運行時可以通過反射獲取到
RetentionPolicy.CLASS 默認的保留策略,註解會在class字節碼文件中存在,但運行時無法獲得
RetentionPolicy.SOURCE 註解僅存在於源碼中,在class字節碼文件中不包含
2. 創建一個自定義註解 - 作用於類
1. 創建一個註解類
- package com.test.www;
- import java.lang.annotation.Documented;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Inherited;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- /**
- * 定義一個用戶名的自定義註解
- * @author zhuli
- * @date 2014-7-5
- */
- @Documented //文檔
- @Retention(RetentionPolicy.RUNTIME) //在運行時可以獲取
- @Target({ ElementType.TYPE, ElementType.METHOD}) //作用到類,方法,接口上等
- @Inherited //子類會繼承
- public @interface UserNameAnnotations {
- public String value() default ""; //使用的時候 @UserNameAnnotations(value="xxx")
- }
package com.test.www;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 定義一個用戶名的自定義註解
* @author zhuli
* @date 2014-7-5
*/
@Documented //文檔
@Retention(RetentionPolicy.RUNTIME) //在運行時可以獲取
@Target({ ElementType.TYPE, ElementType.METHOD}) //作用到類,方法,接口上等
@Inherited //子類會繼承
public @interface UserNameAnnotations {
public String value() default ""; //使用的時候 @UserNameAnnotations(value="xxx")
}
2. 創建一個Test類
- package com.test.www;
- /**
- * 一個註解的測試類
- * @author zhuli
- * @date 2014-7-5
- */
- //注入註解作用於類上面
- //可以通過反射 獲取類的信息之後 獲取得到這個註解的值
- @UserNameAnnotations(value = "initphp")
- public class Test {
- private String userName;
- public String getUserName() {
- return userName;
- }
- public void setUserName(String userName) {
- this.userName = userName;
- }
- }
package com.test.www;
/**
* 一個註解的測試類
* @author zhuli
* @date 2014-7-5
*/
//注入註解作用於類上面
//可以通過反射 獲取類的信息之後 獲取得到這個註解的值
@UserNameAnnotations(value = "initphp")
public class Test {
private String userName;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
3. 測試類
- package com.test.www;
- public class mainTest {
- public static void main(String[] args) {
- Class<Test> testClass = Test.class;
- //因爲註解是作用於類上面的,所以可以通過isAnnotationPresent來判斷是否是一個
- //有UserNameAnnotations註解的類
- if (testClass.isAnnotationPresent(UserNameAnnotations.class)) {
- System.out.println("this is a Annotations class");
- //通過getAnnotation可以獲取註解對象
- UserNameAnnotations userNameAnnotations = (UserNameAnnotations) testClass.
- getAnnotation(UserNameAnnotations.class);
- if (userNameAnnotations != null) {
- System.out.println("value:" + userNameAnnotations.value());
- } else {
- System.out.println("null");
- }
- } else {
- System.out.println("this is not Annotations class");
- }
- }
- }
package com.test.www;
public class mainTest {
public static void main(String[] args) {
Class<Test> testClass = Test.class;
//因爲註解是作用於類上面的,所以可以通過isAnnotationPresent來判斷是否是一個
//有UserNameAnnotations註解的類
if (testClass.isAnnotationPresent(UserNameAnnotations.class)) {
System.out.println("this is a Annotations class");
//通過getAnnotation可以獲取註解對象
UserNameAnnotations userNameAnnotations = (UserNameAnnotations) testClass.
getAnnotation(UserNameAnnotations.class);
if (userNameAnnotations != null) {
System.out.println("value:" + userNameAnnotations.value());
} else {
System.out.println("null");
}
} else {
System.out.println("this is not Annotations class");
}
}
}
4. 輸出:
- this is a Annotations class
- value:initphp
this is a Annotations class
value:initphp
3. 創建一個自定義註解 - 作用於方法
1. 自定義註解類
- package com.test.www;
- import java.lang.annotation.Documented;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- /**
- * 定義一個作用到方法的註解
- * @author zhuli.zhul
- * @date 2014-7-5
- */
- @Documented//文檔
- @Retention(RetentionPolicy.RUNTIME)//在運行時可以獲取
- @Target({ ElementType.TYPE, ElementType.METHOD })//作用到類,方法,接口上等
- public @interface MethodType {
- //枚舉類型
- public enum MethodTypeEnum {
- TYPE1, TYPE2
- }
- //實際的值
- public MethodTypeEnum methodType() default MethodTypeEnum.TYPE1;
- }
package com.test.www;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 定義一個作用到方法的註解
* @author zhuli.zhul
* @date 2014-7-5
*/
@Documented//文檔
@Retention(RetentionPolicy.RUNTIME)//在運行時可以獲取
@Target({ ElementType.TYPE, ElementType.METHOD })//作用到類,方法,接口上等
public @interface MethodType {
//枚舉類型
public enum MethodTypeEnum {
TYPE1, TYPE2
}
//實際的值
public MethodTypeEnum methodType() default MethodTypeEnum.TYPE1;
}
2. 創建一個使用註解的類
- package com.test.www;
- import com.test.www.MethodType.MethodTypeEnum;
- /**
- * 一個註解的測試類
- * @author zhuli
- * @date 2014-7-5
- */
- //注入註解作用於類上面
- //可以通過反射 獲取類的信息之後 獲取得到這個註解的值
- @UserNameAnnotations(value = "initphp")
- public class Test {
- private String userName;
- //註解到
- @MethodType(methodType=MethodTypeEnum.TYPE2)
- public String getUserName() {
- return userName;
- }
- public void setUserName(String userName) {
- this.userName = userName;
- }
- }
package com.test.www;
import com.test.www.MethodType.MethodTypeEnum;
/**
* 一個註解的測試類
* @author zhuli
* @date 2014-7-5
*/
//注入註解作用於類上面
//可以通過反射 獲取類的信息之後 獲取得到這個註解的值
@UserNameAnnotations(value = "initphp")
public class Test {
private String userName;
//註解到
@MethodType(methodType=MethodTypeEnum.TYPE2)
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
3. 創建main入口
- package com.test.www;
- import java.lang.reflect.Method;
- import com.test.www.MethodType.MethodTypeEnum;
- public class mainTest {
- public static void main(String[] args) {
- Class<Test> testClass = Test.class;
- try {
- //因爲是註解到method上的,所以首先要獲取這個方法
- Method method = testClass.getDeclaredMethod("getUserName");
- //判斷這個方法上是否有這個註解
- if (method.isAnnotationPresent(MethodType.class)) {
- System.out.println("this is a method Annotation");
- //如果有這個註解,則獲取註解類
- MethodType methodType = (MethodType) method.getAnnotation(MethodType.class);
- if (methodType != null) {
- if (MethodTypeEnum.TYPE1.equals(methodType.methodType())) {
- System.out.println("this is TYPE1");
- } else {
- System.out.println("this is TYPE2");
- }
- }
- } else {
- System.out.println("this is not a method Annotation");
- }
- } catch (Exception e) {
- }
- }
- }
package com.test.www;
import java.lang.reflect.Method;
import com.test.www.MethodType.MethodTypeEnum;
public class mainTest {
public static void main(String[] args) {
Class<Test> testClass = Test.class;
try {
//因爲是註解到method上的,所以首先要獲取這個方法
Method method = testClass.getDeclaredMethod("getUserName");
//判斷這個方法上是否有這個註解
if (method.isAnnotationPresent(MethodType.class)) {
System.out.println("this is a method Annotation");
//如果有這個註解,則獲取註解類
MethodType methodType = (MethodType) method.getAnnotation(MethodType.class);
if (methodType != null) {
if (MethodTypeEnum.TYPE1.equals(methodType.methodType())) {
System.out.println("this is TYPE1");
} else {
System.out.println("this is TYPE2");
}
}
} else {
System.out.println("this is not a method Annotation");
}
} catch (Exception e) {
}
}
}
4. 輸出:
- this is a method Annotation
- this is TYPE2
this is a method Annotation
this is TYPE2
4. 創建一個自定義註解 - 作用於域
1. 創建一個自定義註解
- package com.test.www;
- import java.lang.annotation.Documented;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- /**
- * 定義一個作用到域上的自定義註解
- * @author zhuli
- * @date 2014-7-5
- */
- @Documented//文檔
- @Retention(RetentionPolicy.RUNTIME)//在運行時可以獲取
- @Target({ ElementType.FIELD })//作用到類的域上面
- public @interface FieldAnnotations {
- public String value() default ""; //使用的時候 @FieldAnnotations(value="xxx")
- }
package com.test.www;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 定義一個作用到域上的自定義註解
* @author zhuli
* @date 2014-7-5
*/
@Documented//文檔
@Retention(RetentionPolicy.RUNTIME)//在運行時可以獲取
@Target({ ElementType.FIELD })//作用到類的域上面
public @interface FieldAnnotations {
public String value() default ""; //使用的時候 @FieldAnnotations(value="xxx")
}
2. 創建一個使用註解的類
- package com.test.www;
- import com.test.www.MethodType.MethodTypeEnum;
- /**
- * 一個註解的測試類
- * @author zhuli
- * @date 2014-7-5
- */
- //注入註解作用於類上面
- //可以通過反射 獲取類的信息之後 獲取得到這個註解的值
- @UserNameAnnotations(value = "initphp")
- public class Test {
- @FieldAnnotations(value="zhuli")
- private String userName;
- //註解到
- @MethodType(methodType=MethodTypeEnum.TYPE2)
- public String getUserName() {
- return userName;
- }
- public void setUserName(String userName) {
- this.userName = userName;
- }
- }
package com.test.www;
import com.test.www.MethodType.MethodTypeEnum;
/**
* 一個註解的測試類
* @author zhuli
* @date 2014-7-5
*/
//注入註解作用於類上面
//可以通過反射 獲取類的信息之後 獲取得到這個註解的值
@UserNameAnnotations(value = "initphp")
public class Test {
@FieldAnnotations(value="zhuli")
private String userName;
//註解到
@MethodType(methodType=MethodTypeEnum.TYPE2)
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
3. 創建main入口類
- package com.test.www;
- import java.lang.reflect.Field;
- public class mainTest {
- public static void main(String[] args) {
- Test test = new Test();
- Class<Test> testClass = Test.class;
- try {
- //因爲是註解到Field上的,所以首先要獲取這個字段
- Field field = testClass.getDeclaredField("userName");
- //判斷這個Field上是否有這個註解
- if (field.isAnnotationPresent(FieldAnnotations.class)) {
- System.out.println("this is a field Annotation");
- //如果有這個註解,則獲取註解類
- FieldAnnotations fieldAnnotations = (FieldAnnotations) field.getAnnotation(FieldAnnotations.class);
- if (fieldAnnotations != null) {
- //通過反射給私有變量賦值
- field.setAccessible(true);
- field.set(test, fieldAnnotations.value());
- System.out.println("value:" + test.getUserName());
- }
- } else {
- System.out.println("this is not a field Annotation");
- }
- } catch (Exception e) {
- }
- }
- }
package com.test.www;
import java.lang.reflect.Field;
public class mainTest {
public static void main(String[] args) {
Test test = new Test();
Class<Test> testClass = Test.class;
try {
//因爲是註解到Field上的,所以首先要獲取這個字段
Field field = testClass.getDeclaredField("userName");
//判斷這個Field上是否有這個註解
if (field.isAnnotationPresent(FieldAnnotations.class)) {
System.out.println("this is a field Annotation");
//如果有這個註解,則獲取註解類
FieldAnnotations fieldAnnotations = (FieldAnnotations) field.getAnnotation(FieldAnnotations.class);
if (fieldAnnotations != null) {
//通過反射給私有變量賦值
field.setAccessible(true);
field.set(test, fieldAnnotations.value());
System.out.println("value:" + test.getUserName());
}
} else {
System.out.println("this is not a field Annotation");
}
} catch (Exception e) {
}
}
}
4. 輸出:
- this is a field Annotation
- value:zhuli
this is a field Annotation
value:zhuli