java注解是在JDK5時引入的新特性,大多數框架(SpringBoot、MyBatis、Quartz)背后都在大量使用注解開發。
一、先進行一個小試驗,了解注解開發流程
建立maven項目annotation:
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
2 <modelVersion>4.0.0</modelVersion>
3 <groupId>org.guangsoft</groupId>
4 <artifactId>annotation</artifactId>
5 <version>1.0</version>
6 <packaging>war</packaging>
7 <name>annotation</name>
8 </project>
基礎注解類:
1 package org.guangsoft.annotation.entity; 2
3 import java.lang.annotation.ElementType; 4 import java.lang.annotation.Retention; 5 import java.lang.annotation.RetentionPolicy; 6 import java.lang.annotation.Target; 7
8 @Target(ElementType.METHOD) 9 @Retention(RetentionPolicy.RUNTIME) 10 public @interface DBInfo { 11 String driver() default ""; 12 String url() default ""; 13 String username() default ""; 14 String password() default ""; 15 }
其中,@Target表示此注解只能用於方法上,@Retention表示該注解生存期是運行時
測試類:
1 package org.guangsoft.annotation.utils; 2
3 import java.lang.reflect.Method; 4
5 import org.guangsoft.annotation.entity.DBInfo; 6
7 public class JDBCUtil1 { 8
9 @DBInfo(url="guanghe:annotation") 10 public static void getConnection() throws Exception { 11 Method method = JDBCUtil1.class.getMethod("getConnection", null); 12 DBInfo info = method.getAnnotation(DBInfo.class); 13 System.out.println(info.url()); 14 } 15
16 public static void main(String args[]) { 17 try { 18 JDBCUtil1.getConnection(); 19 } catch(Exception e) { 20 e.printStackTrace(); 21 } 22 } 23 }
從這里我們可以看出,獲取注解用的是反射。
運行結果:
二、注解開發基本知識
@Target類型
1 public enum ElementType { 2 /**標明該注解可以用於類、接口(包括注解類型)或enum聲明*/
3 TYPE, 4 /** 標明該注解可以用於字段(域)聲明,包括enum實例 */
5 FIELD, 6 /** 標明該注解可以用於方法聲明 */
7 METHOD, 8 /** 標明該注解可以用於參數聲明 */
9 PARAMETER, 10 /** 標明注解可以用於構造函數聲明 */
11 CONSTRUCTOR, 12 /** 標明注解可以用於局部變量聲明 */
13 LOCAL_VARIABLE, 14 /** 標明注解可以用於注解聲明(應用於另一個注解上)*/
15 ANNOTATION_TYPE, 16 /** 標明注解可以用於包聲明 */
17 PACKAGE, 18 /**
19 * 標明注解可以用於類型參數聲明(1.8新加入) 20 * @since 1.8 21 */
22 TYPE_PARAMETER, 23 /**
24 * 類型使用聲明(1.8新加入) 25 * @since 1.8 26 */
27 TYPE_USE 28 }
@Target使用方法:
1 @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
@Retention類型:
SOURCE:
注解將被編譯器丟棄(該類型的注解信息只會保留在源碼里,源碼經過編譯后,注解信息會被丟棄,不會保留在編譯好的class文件里)
CLASS:
注解在class文件中可用,但會被VM丟棄(該類型的注解信息會保留在源碼里和class文件里,在執行的時候,不會加載到虛擬機中),請注意,當注解未定義Retention值時,默認值是CLASS,如Java內置注解,@Override、@Deprecated、@SuppressWarnning等
RUNTIME:
注解信息將在運行期(JVM)也保留,因此可以通過反射機制讀取注解的信息(源碼、class文件和執行的時候都有注解的信息),如SpringMvc中的@Controller、@Autowired、@RequestMapping等。
@Retention使用方法:
1 @Retention(RetentionPolicy.RUNTIME) //只允許使用一種生命周期
支持類型:
所有基本類型(int,float,boolean,byte,double,char,long,short)String Class enum Annotation 以及上述類型的數組
1 public @interface AnnotationElement { 2 //枚舉類型
3 enum Status {FIXED,NORMAL}; 4 //聲明枚舉
5 Status status() default Status.FIXED; 6 //布爾類型
7 boolean showSupport() default false; 8 //String類型
9 String name()default ""; 10 //class類型
11 Class<?> testCase() default Void.class; 12 //注解嵌套
13 Reference reference() default @Reference(next=true); 14 //數組類型
15 long[] value(); 16 }
注解書寫規定
注解書寫要求以(key1 = value1, key2 = value2)的形式書寫。
其中value如果是多個值要用{}將value括起來,即(key1 = value1, key2={value21,value22})的形式。
當注解中定義了名為value的元素,並且在使用該注解時,如果該元素是唯一需要賦值的一個元素,那么此時無需使用key=value的語法,而只需在括號()內給出value元素所需的值即可。
內置注解
java提供了許多內置注解,主要介紹三個:
@Override:用於標明此方法覆蓋了父類的方法
@Deprecated:用於標明已經過時的方法或類
@SuppressWarnnings:用於有選擇的關閉編譯器對類、方法、成員變量、變量初始化的警告
1 @Target(ElementType.METHOD) 2 @Retention(RetentionPolicy.SOURCE) 3 public @interface Override { 4 } 5
6 @Documented 7 @Retention(RetentionPolicy.RUNTIME) 8 @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE}) 9 public @interface Deprecated { 10 } 11
12 @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) 13 @Retention(RetentionPolicy.SOURCE) 14 public @interface SuppressWarnings { 15 String[] value(); 16 }
利用反射獲取注解
<A extends Annotation> getAnnotation(Class<A> annotationClass) 該元素如果存在指定類型的注解,則返回這些注解,否則返回 null。
Annotation[] getAnnotations() 返回此元素上存在的所有注解,包括從父類繼承的
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) 如果指定類型的注解存在於此元素上,則返回 true,否則返回 false。
Annotation[] getDeclaredAnnotations() 返回直接存在於此元素上的所有注解,注意,不包括父類的注解,調用者可以隨意修改返回的數組;這不會對其他調用者返回的數組產生任何影響,沒有則返回長度為0的數組