註解是java5引入的特性,在代碼中插入一種註釋化的信息,用於對代碼進行說明,能夠對包、類、接口、字段、方法參數、局部變量等進行註解。註解也叫元數據(meta data)。這些註解信息能夠在編譯期使用預編譯工具進行處理(pre-compiler tools),也能夠在運行期使用 Java 反射機制進行處理。
它主要的做用有如下四方面:java
通常註解能夠分爲三類:app
@Override
、@Deprecated
和@SuppressWarnings
,分別用於標明重寫某個方法、標明某個類或方法過期、標明要忽略的警告,用這些註解標明後編譯器就會進行檢查。@Retention
、@Target
、@Inherited
、@Documented
,@Retention
用於標明註解被保留的階段,@Target
用於標明註解使用的範圍,@Inherited用於標明註解可繼承,@Documented
用於標明是否生成javadoc文檔。爲何在類、方法上加一個註解,就能夠經過getAnnotation()獲取到申明的註解的值?
好比:ide
@Test("test") public class AnnotationTest { public void test(){ } }
對於註解test就能夠在運行時經過AnnotationTest.class.getAnnotation(Test.class)獲取註解聲明的值。工具
在AnnotationTest類被編譯後,在對應的AnnotationTest.class文件中會包含一個RuntimeVisibleAnnotations屬性,因爲這個註解是做用在類上,因此此屬性被添加到類的屬性集上。即Test註解的鍵值對value=test會被記錄起來。而當JVM加載AnnotationTest.class文件字節碼時,就會將RuntimeVisibleAnnotations屬性值保存到AnnotationTest的Class對象中,因而就能夠經過AnnotationTest.class.getAnnotation(Test.class)獲取到Test註解對象,進而再經過Test註解對象獲取到Test裏面的屬性值。
這裏可能會有疑問,Test註解對象是什麼?其實註解被編譯後的本質就是一個繼承Annotation接口的接口,因此@Test
其實就是「public interface Test extends Annotation」,當咱們經過AnnotationTest.class.getAnnotation(Test.class)調用時,JDK會經過動態代理生成一個實現了Test接口的對象,並把將RuntimeVisibleAnnotations屬性值設置進此對象中,此對象即爲Test註解對象,經過它的value()方法就能夠獲取到註解值。.net
註解能夠經過做用的類型可分爲:類註解、方法註解、參數註解、變量註解。代理
類註解
訪問類註解的例子:code
Class aClass = TheClass.class; Annotation[] annotations = aClass.getAnnotations(); for(Annotation annotation : annotations){ if(annotation instanceof MyAnnotation){ MyAnnotation myAnnotation = (MyAnnotation) annotation; System.out.println("name: " + myAnnotation.name()); System.out.println("value: " + myAnnotation.value()); } }
此方法獲取到的是該類的全部註解,也可指定某一個類:對象
Class aClass = TheClass.class; Annotation annotation = aClass.getAnnotation(MyAnnotation.class); if(annotation instanceof MyAnnotation){ MyAnnotation myAnnotation = (MyAnnotation) annotation; System.out.println("name: " + myAnnotation.name()); System.out.println("value: " + myAnnotation.value()); }
Spring中的@Service``@Controller
便是如此。blog
方法註解繼承
public class TheClass { @MyAnnotation(name="someName", value = "Hello World") public void doSomething(){} }
獲取方法對象的指定註解:
Method method = ... // 獲取方法對象 Annotation annotation = method.getAnnotation(MyAnnotation.class); if(annotation instanceof MyAnnotation){ MyAnnotation myAnnotation = (MyAnnotation) annotation; System.out.println("name: " + myAnnotation.name()); System.out.println("value: " + myAnnotation.value()); }
SpringMVC中的@RequestMapping
便是如此。
參數註解
方法的參數也能夠添加註解:
public class TheClass { public static void doSomethingElse( @MyAnnotation(name="aName", value="aValue") String parameter){ } }
訪問註解:
Method method = ... //獲取方法對象 Annotation[][] parameterAnnotations = method.getParameterAnnotations(); Class[] parameterTypes = method.getParameterTypes(); int i=0; for(Annotation[] annotations : parameterAnnotations){ Class parameterType = parameterTypes[i++]; for(Annotation annotation : annotations){ if(annotation instanceof MyAnnotation){ MyAnnotation myAnnotation = (MyAnnotation) annotation; System.out.println("param: " + parameterType.getName()); System.out.println("name : " + myAnnotation.name()); System.out.println("value: " + myAnnotation.value()); } } }
Mybatis中的@Param
便是如此
變量註解
使用註解:
public class TheClass { @MyAnnotation(name="someName", value = "Hello World") public String myField = null; }
獲取註解:
Field field = ...//獲取方法對象</pre> <pre> Annotation annotation = field.getAnnotation(MyAnnotation.class); if(annotation instanceof MyAnnotation){ MyAnnotation myAnnotation = (MyAnnotation) annotation; System.out.println("name: " + myAnnotation.name()); System.out.println("value: " + myAnnotation.value()); }
Spring中的@Inject``@Resource
便是如此。