Java注解annotation用法和自定義注解處理器(轉載)
轉自: http://computerdragon.blog.51cto.com/6235984/1210969
前言:在J2EE中,注解使得開發更加便利,省去了生成XML文件的過程,在Hibernate實體聲明中,可以簡簡單單的用幾個注解就可以免去生成一個XML的文件操作。這里就主要論述一下annotation的用法和自定義注解處理器。當在創建描述符性質的類或接口時,有大量重復性的工作時候,就可以利用注解來實現。
基本語法:
Java目前包括三種標準注解和四種元注解。元注解主要負責注解其他注解的。
三種標準注解:
@Override,表示當前的方法定義覆蓋了父類中的方法。必須要有相同的方法簽名即(方法名,參數類型,參數順序,參數個數)都一樣。否則在編譯過程中發出錯誤提示。
@Deprecated,對不應該再使用的方法添加注解,當使用這個方法的時候,會在編譯時候顯示提示信息。
@SuppressWarnings,關閉不當的編譯器報警信息
四種元注解:
@Target,表示該注解可以用什么地方。
如CONSTRUCTOR,構造器聲明;FIELD,域聲明;METHOD,方法聲明;TYPE,類,接口或enum聲明
@Retention,表示需要在什么級別保存該注解信息。
如SOURCE,注解將被編譯器丟棄;CLASS,注解在class文件可用,但會被VM丟棄
RUNTIME,VM將在運行期間也保留注解,可以使用反射機制讀取注解信息
@Documented,將此注解包含到Javadoc中。
@Inherited,允許子類繼承父類的注解。
定義注解:
自定義注解是以@interface為標志的。如同一個接口的定義,這里面定義的每個方法名,就是使用注解時候的元素名,方法的返回值就是元素的類型,可以利用default來聲明默認值,不過對于非基本類型,不能設置為null為默認值,一般對于字符串使用空字符串作為其默認值。
如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | package whut.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; //定義一個注解 @Target (ElementType.METHOD) //定義該注解將應用于什么地方,方法或者域 @Retention (RetentionPolicy.RUNTIME) //定義該注解在哪一個級別可用 public @interface UseCase { //注解元素,可以指定默認值,在使用注解的時候,可以直接給元素賦值如id=5 public int id(); public String description() default "no description" ; //利用枚舉來設置參數類型 public enum ParameterType { STRING, SHORT, INT, BOOL, LONG, OBJECT }; // 默認值,在使用注解的時候,只需要為元素賦值 public ParameterType type() default ParameterType.STRING; } |
使用注解:
在類中任意的域值前,或者方法前等直接@注解名,如@UseCase(id=5),使用注解的過程中,必須對于沒有設置默認值的元素進行賦值操作,對于每個元素進行按照名-值對的方式賦值。如果在注解定義中有名為value的元素,并且它是唯一需要賦值的,可以直接在括號里給出value所需要的值。
注解是不能繼承的。
下面是一個基本的利用非apt實現的注解處理器模型。
這個模型可以注解實體,進行數據庫的映射建表操作。是最最基本的操作。
注解定義:將四個注解名是在不同的文件中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | package whut.annotationDB; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target (ElementType.FIELD) @Retention (RetentionPolicy.RUNTIME) //定義字段的約束 public @interface Constraints { boolean primaryKey() default false ; boolean allowNull() default true ; boolean unique() default false ; } //////////////////////////// package whut.annotationDB; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target (ElementType.TYPE) //類,接口或enum @Retention (RetentionPolicy.RUNTIME) //定義表名的注解 public @interface DBTable { public String name() default "" ; } /////////////////////////// package whut.annotationDB; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target (ElementType.FIELD) //類,接口或enum @Retention (RetentionPolicy.RUNTIME) public @interface SQLInteger { String name() default "" ; //嵌套注解的功能,將column類型的數據庫約束信息嵌入其中 Constraints constraints() default @Constraints ; } /////////////////////////////// package whut.annotationDB; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target (ElementType.FIELD) //類,接口或enum @Retention (RetentionPolicy.RUNTIME) public @interface SQLString { int value() default 0 ; String name() default "" ; //注解元素中引用別的注解, Constraints constraints() default @Constraints ; } |
實體使用注解:這里是運用了運行時候處理注解,所以RetentionPolicy.RUNTIME
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | package whut.annotationDB; @DBTable (name= "MEMBER" ) public class Member { //在使用注解過程中,如果有元素是value,并且只有value需要賦值, //則只需要在()中將值寫入 @SQLString ( 30 ) private String firstName; @SQLString ( 50 ) private String lastName; @SQLInteger private Integer age; @SQLString (value= 30 ,constraints= @Constraints (primaryKey= true )) private String handle; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this .firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this .lastName = lastName; } public Integer getAge() { return age; } public void setAge(Integer age) { this .age = age; } public String getHandle() { return handle; } public void setHandle(String handle) { this .handle = handle; } } |
具體的非apt實現的注解處理器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | package whut.annotationDB; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class TableCreator { public Connection getConnection() { String user = "root" ; String password = "" ; String serverUrl = "jdbc:mysql://localhost:3306/carrent?user=root&password=" ; try { Class.forName( "com.mysql.jdbc.Driver" ); Connection con = DriverManager.getConnection(serverUrl, user, password); return con; } catch (Exception e) { e.printStackTrace(); return null ; } } //實現創建表 public static void main(String[] args) { TableCreator tc = new TableCreator(); tc.executeCreateDB(Member. class ); } public void executeCreateDB(Class<?> entity) { String sqlStr = explainAnnotation(entity); Connection con = getConnection(); PreparedStatement psql = null ; if (con != null && !sqlStr.equals( "error" )) { try { psql = con.prepareStatement(sqlStr); psql.execute(); } catch (SQLException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (psql != null ) psql.close(); } catch (SQLException e) { e.printStackTrace(); } try { if (con != null ) psql.close(); } catch (SQLException e) { e.printStackTrace(); } } } else System.out.println( "failure to..." ); } // 真正的處理器,Class<?>必須用這個表明 public String explainAnnotation(Class<?> entity) { // 獲取指定類型的注解 DBTable dbtable = entity.getAnnotation(DBTable. class ); if (dbtable == null ) { System.out.println( "No DBTable annotation in class" + entity.getName()); return "error" ; } else { String tableName = dbtable.name(); // 獲取注解name值,即表名稱 // 當沒有設置name值,直接利用類的名作為表名 if (tableName.length() < 1 ) tableName = entity.getName().toUpperCase(); // 轉換大寫 // 準備處理字段注解 List<String> columnsDefs = new ArrayList<String>(); // 獲取該類的所有字段 for (Field field : entity.getDeclaredFields()) { String columnName = null ; // 獲取該字段所有的注解 Annotation[] anns = field.getDeclaredAnnotations(); // Annotation[] anns=field.getAnnotations(); // 當有注解的時候 if (anns.length >= 1 ) { // 判斷注解的類型 if (anns[ 0 ] instanceof SQLInteger) { SQLInteger sInt = (SQLInteger) anns[ 0 ]; // 當沒有name時候,將字段大寫為列名 if (sInt.name().length() < 1 ) columnName = field.getName().toUpperCase(); else columnName = sInt.name(); columnsDefs.add(columnName + " INT" + getConstraints(sInt.constraints())); } if (anns[ 0 ] instanceof SQLString) { SQLString sString = (SQLString) anns[ 0 ]; // 當沒有name時候,將字段大寫為列名 if (sString.name().length() < 1 ) columnName = field.getName().toUpperCase(); else columnName = sString.name(); columnsDefs.add(columnName + " VARCHAR(" + sString.value() + ")" + getConstraints(sString.constraints())); } } } StringBuilder createDB = new StringBuilder( "CREATE TABLE " + tableName + "(" ); for (String cols : columnsDefs) createDB.append( " " + cols + "," ); // 移除最后一個,號 String tableSQL = createDB.substring( 0 , createDB.length() - 1 ) + ");" ; // 輸出創建表的過程 System.out.println( "Table Creation SQL is:\n" + tableSQL); return tableSQL; } } // 返回指定的約束 public String getConstraints(Constraints con) { String constras = "" ; if (!con.allowNull()) constras += " NOT NULL" ; if (con.primaryKey()) constras += " PRIMARY KEY" ; if (con.unique()) constras += " UNIQUE" ; return constras; } } |