Java自定義註解——簡易實現spring @Autowired
用過spring的都知道@Autowired,但是類似的註解內部是怎樣實現的呢?下面通過一個小例子來了解一下類似的實現過程
在看這個例子之前需要先對java反射機制有了解,不需要多深入,只需知道反射是幹什麼的就可以了,程式碼很少,不復雜,一看就懂,通過這個例子可以初步認識反射、自定義註解等知識 首先寫自定義註解的程式碼,在寫之前需要先了解以下幾個元註解@Target:
@Target說明了Annotation所修飾的物件範圍:Annotation可被用於 packages、types(類、介面、列舉、Annotation型別)、型別成員(方法、構造方法、成員變數、列舉值)、方法引數和本地變數(如迴圈變數、catch引數)。在Annotation型別的宣告中使用了target可更加明晰其修飾的目標。
作用:用於描述註解的使用範圍(即:被描述的註解可以用在什麼地方)
取值(ElementType)有:
1.CONSTRUCTOR:用於描述構造器
2.FIELD:用於描述域
3.LOCAL_VARIABLE:用於描述區域性變數
4.METHOD:用於描述方法
5.PACKAGE:用於描述包
6.PARAMETER:用於描述引數
7.TYPE:用於描述類、介面(包括註解型別) 或enum宣告
@Retention:
@Retention定義了該Annotation被保留的時間長短:某些Annotation僅出現在原始碼中,而被編譯器丟棄;而另一些卻被編譯在class檔案中;編譯在class檔案中的Annotation可能會被虛擬機器忽略,而另一些在class被裝載時將被讀取(請注意並不影響class的執行,因為Annotation與class在使用上是被分離的)。使用這個meta-Annotation可以對 Annotation的“生命週期”限制。
作用:表示需要在什麼級別儲存該註釋資訊,用於描述註解的生命週期(即:被描述的註解在什麼範圍內有效)
取值(RetentionPoicy)有:
1.SOURCE:在原始檔中有效(即原始檔保留)
2.CLASS:在class檔案中有效(即class保留)
3.RUNTIME:在執行時有效(即執行時保留)
Retention meta-annotation型別有唯一的value作為成員,它的取值來自java.lang.annotation.RetentionPolicy的列舉型別值。
@Documented:
@Documented用於描述其它型別的annotation應該被作為被標註的程式成員的公共API,因此可以被例如javadoc此類的工具文件化。Documented是一個標記註解,沒有成員。
/**
* 測試註解
* @author lc
*
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TestAnnotation {
/**
* 數值
* @return
*/
int num() default 1;
}
接著是使用註解的程式碼
public class Test {
@TestAnnotation(num=45)
private static int a;//使用註解
private int b = 9; //未使用註解的變數,主要是用於做對比
public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
TestZjImpl.set(Test.class);
System.out.println(a);
}
}
最後是通過反射機制給註解的變數賦值
public static void set(Class c) throws IllegalArgumentException, IllegalAccessException{
Field[] fields = c.getDeclaredFields();//獲取所有變數
for(int i=0; i<fields.length;i++){
fields[i].setAccessible(true);//獲取訪問私有變數的許可權
if(fields[i].isAnnotationPresent(TestAnnotation.class)){//判斷是否是使用註解的引數
TestAnnotation t = fields[i].getAnnotation(TestAnnotation.class);
System.out.println("註解中配置的num引數是:"+t.num());
fields[i].set(t, 18);//給變數賦值
}
}
}
程式碼很簡單,一看就懂,spring的@Autowired當然不會這麼簡單,想進一步瞭解的可以看原始碼,其它的用法可以根據示例程式碼自己發揮