- 編譯檢查
Annotation具有“讓編譯器進行編譯檢查的作用”。
例如,@SuppressWarnings, @Deprecated和@Override都具有編譯檢查作用。 - 在反射中使用Annotation
在反射的Class, Method, Field等函數中,有許多於Annotation相關的接口。
這也意味着,我們可以在反射中解析並使用Annotation。 - 根據Annotation生成幫助文檔
通過給Annotation注解加上@Documented標簽,能使該Annotation標簽出現在javadoc中。 - 能夠幫忙查看查看代碼
通過@Override, @Deprecated等,我們能很方便的了解程序的大致結構。
另外,我們也可以通過自定義Annotation來實現一些功能。
5.注解處理器
如果沒有用來讀取注解的方法和工作,那么注解也就不會比注釋更有用處了。使用注解的過程中,很重要的一部分就是創建於使用注解處理器。Java SE5擴展了反射機制的API,以幫助程序員快速的構造自定義注解處理器。 - 在框架中的作用
在開發Java程序,尤其是Java EE應用的時候,總是免不了與各種配置文件打交道。以Java EE中典型的S(pring)S(truts)H(ibernate)架構來說,Spring、Struts和Hibernate這三個框架都有自己的XML格式的配置文件。這些配置文件需要與Java源代碼保存同步,否則的話就可能出現錯誤。而且這些錯誤有可能到了運行時刻才被發現。把同一份信息保存在兩個地方,總是個壞的主意。理想的情況是在一個地方維護這些信息就好了。其它部分所需的信息則通過自動的方式來生成。JDK 5中引入了源代碼中的注解(annotation)這一機制。注解使得Java源代碼中不但可以包含功能性的實現代碼,還可以添加元數據。注解的功能類似於代碼中的注釋,所不同的是注解不是提供代碼功能的說明,而是實現程序功能的重要組成部分。Java注解已經在很多框架中得到了廣泛的使用,用來簡化程序中的配置。
因為注解大多都有自己的配置參數,而配置參數以名值對的方式出現,所以從某種角度來說,可以把注解看成是一個XML元素,該元素可以有不同的預定義的屬性。而屬性的值是可以在聲明該元素的時候自行指定的。在代碼中使用注解,就相當於把一部分元數據從XML文件移到了代碼本身之中,在一個地方管理和維護。
上面兩段話其實已經闡述了java注解的主要作用之一,就是跟蹤代碼依賴性,實現替代配置文件功能。比較常見的是Spring等框架中的基於注解配置。現在的框架很多都使用了這種方式來減少配置文件的數量。基本上秉持着這么一個原則,與具體場景相關的配置應該使用注解的方式與數據關聯,與具體場景無關的配置放於配置文件中。在另一方面我們還可以在通過設置注解的@Retention 級別在運行時使用反射對不同的注解進行處理。
怎么使用呢?
例子:先利用反射,獲取到注解,然后把利用注解實例化該類的對象
下面有一個例子:(自己寫的哦)
定義一個注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitProvider {
/*供應商編號*/
public int id() default -1;
/*供應商名稱*/
public String name() default "";
/*供應商地址*/
public String address() default "";
}
對一個類使用注解
@FruitProvider(id = 1728, name = "why", address = "shenzhen")
public class Apple {
private int appleID;
private String appleProvidername;
private String appleprovideraddress;
public int getAppleID() {
return appleID;
}
public void setAppleID(int appleID) {
this.appleID = appleID;
}
public String getAppleProvidername() {
return appleProvidername;
}
public void setAppleProvidername(String appleProvidername) {
this.appleProvidername = appleProvidername;
}
public String getAppleprovideraddress() {
return appleprovideraddress;
}
public void setAppleprovideraddress(String appleprovideraddress) {
this.appleprovideraddress = appleprovideraddress;
}
}
注解處理器
public class FruitInfoUtil {
public static Apple getAApple(Class<?> clazz) throws Exception{
FruitProvider fb = clazz.getAnnotation(FruitProvider.class);//通過反射獲取處理注釋
//通過newInstance()生成Apple實例,利用反射的結果進行設置
Apple ap = (Apple)clazz.newInstance();
ap.setAppleID(fb.id());
ap.setAppleProvidername(fb.name());
ap.setAppleprovideraddress(fb.address());
return ap;
}
}
public class Main {
public static void main(String[] args) throws Exception{
Apple a = FruitInfoUtil.getAApple(Apple.class);
System.out.println("蘋果商的ID為:"+a.getAppleID());
System.out.println("蘋果商的名字為:"+a.getAppleProvidername());
System.out.println("蘋果商的地址為:"+a.getAppleprovideraddress());
}
}
這個實例就很好的說明,現在的框架很多都使用了這種方式來減少配置文件的數量。(因為配置就在代碼里面了)。
部分來源:簡書[ALEXIRC]