Java中的註解的應用越來越廣泛,測試框架JUnit4, 以及Spring,Hibernate,Struts,MyBatis,JPA等等都包含了對註解的支持。在C#中的Attribute特性就是和Java中的註解是對應的。使用註解是爲了編程更簡便。但是我們得知道註解是做什麼的,最好是能夠自己的代碼中可以自定義註解,提高生產率。
下面就來說一下Annotation,先說一下基本知識,然後用一個例子把這些串起來。
-------------------------------------------------------元註解----------------------------------------------------------------------------
Java註解分類:元註解、一般的註解。元數據,是數據的數據,數據的信息。那麼元註解同樣道理,是註解的註解,註解的信息。java中的元註解有:@Retention @Target @Document @Inherited:
@Document 是用於javadoc的。一般很少使用。
@Retention: 定義註解的保留策略:
SOURCE :只是在源代碼中保留。編譯後的class文件中就不會有的。
CLASS:會保留到Class文件中,在類的加載器把類加載到JVM中,就會去掉了。
RUNTIME:保留至運行時,也就是可以在JVM中使用了。這種最常用。
@Target:定義註解的作用目標:
@Target(ElementType.TYPE) //接口、類、枚舉、註解
@Inherited 繼承其他的註解
這些都元註解。
------------------------------------------------------------註解---------------------------------------------------------------------------
Annotation本身不是個註解,但是我們寫的註解都會隱藏的繼承這個類。
註解的聲明:
1 @Retention @Target 2 3 public @interface 註解名{ 4 5 }
@interface,用於表示註解。由interface知道註解中都是以接口的方式書寫的,就是以接口中方法的書寫方式書寫。
註解中的方法,稱爲註解的元素。它的語法是:
public elementType elementName() [default value]; |
elementName, 元素名,命名方式就是java中方法的命名方式。
elementType ,元素的類型,可以使用的元素類型有:
原生類型:byte,short,int,long,float,double
字符串:String,
日期:Date
Class
enum
可以設置默認值。
如何使用就不用說了。
對於註解的處理,是通過Java中的反射來的。
題外話:如果沒有反射,就沒有Java中的各種框架。可見反射多麼的重要。
-----------------------------------------------------示例--------------------------------------------------------------------------------
設計一個Input註解,用於將Java bean中屬性輸出成HTML中的Input元素。這個是我即是寫的,沒有什麼實際意義,但是用於說明註解,就夠用了,它包括了註解的各種用法:
Input註解:
1 @Target(value={ElementType.FIELD}) 2 @Retention(RetentionPolicy.RUNTIME) 3 public @interface Input { 4 public String value() default ""; // 元素是普通類型 5 public String style() default ""; 6 public String clazz() default ""; 7 public String id() default ""; 8 public String title() default ""; 9 public String volidator() default ""; 10 public Checked checked() default @Checked(checked=false); // 元素是註解 11 public InputType type() default InputType.text; // 元素是枚舉 12 13 14 enum InputType { 15 text, radio, checkbox, button, password, file; 16 } 17 }
1 @Target(value={ElementType.FIELD}) 2 @Retention(RetentionPolicy.RUNTIME) 3 public @interface Checked { 4 public boolean checked() default false; 5 }
上面這兩個類定義了兩個註解,Checked註解又是作爲Input註解的元素的。
1 @Target(value={ElementType.FIELD}) 2 @Retention(RetentionPolicy.RUNTIME) 3 public @interface DateType { 4 public String format() default "yyyy-MM-dd"; 5 }
這個註解,是一個日期類型的註解。
定義一個Java bean,使用上面定義的三個註解:
1 public class Person { 2 3 @Input(title="編號") 4 private int id; 5 @Input(title="姓名") 6 private String name; 7 @Input(title="年齡") 8 private int age; 9 @Input(title="出生日期") 10 @DateType(format="yyyy-MM-dd HH:mm:ss") 11 private Date birthday; 12 @Input(title="地址") 13 private String address; 14 @Input(title="性別", checked=@Checked(checked=true)) 15 private String gender; 16 @Input(title="口令", type=InputType.password) 17 private String password; 18 19 public String getGender() { 20 return gender; 21 } 22 public void setGender(String gender) { 23 this.gender = gender; 24 } 25 public int getId() { 26 return id; 27 } 28 public void setId(int id) { 29 this.id = id; 30 } 31 public String getName() { 32 return name; 33 } 34 public void setName(String name) { 35 this.name = name; 36 } 37 public int getAge() { 38 return age; 39 } 40 public void setAge(int age) { 41 this.age = age; 42 } 43 public Date getBirthday() { 44 return birthday; 45 } 46 public void setBirthday(Date birthday) { 47 this.birthday = birthday; 48 } 49 public String getAddress() { 50 return address; 51 } 52 public void setAddress(String address) { 53 this.address = address; 54 } 55 56 57 }
定義一個Writer,處理上面的註解,:
1 package com.fjn.tools.annotation; 2 3 import java.io.PrintWriter; 4 import java.lang.reflect.Field; 5 import java.util.Date; 6 /** 7 * 包裝PrintWriter 8 */ 9 import com.fjn.tools.common.DateHelper; 10 @SuppressWarnings("rawtypes") 11 public class BeanWriter<T> extends PrintWriter{ 12 private PrintWriter out; 13 private T bean; 14 public BeanWriter(PrintWriter out) { 15 super(out); 16 this.out=out; 17 } 18 19 public void write(){ 20 if(bean==null) return; 21 22 Class clazz=bean.getClass(); 23 Field[] fields=clazz.getDeclaredFields(); 24 StringBuffer sbf=new StringBuffer();; 25 for (int i = 0; i < fields.length; i++) { 26 27 Input input=fields[i].getAnnotation(Input.class); 28 if(input == null) continue; 29 fields[i].setAccessible(true); 30 Object value=null; 31 // 日期要判斷格式 32 if(fields[i].getType()==Date.class || fields[i].getType()==java.sql.Date.class){ 33 value=getDateString(fields[i], bean); 34 }else { 35 try { 36 value=fields[i].get(bean); 37 } catch (Exception e1) { 38 e1.printStackTrace(); 39 } 40 } 41 42 sbf.append("<input type='") 43 .append(input.type().name()) 44 .append("' name='") 45 .append(fields[i].getName()) 46 .append("' id='") 47 .append(input.id()) 48 .append("' style='") 49 .append(input.style()) 50 .append("' title='") 51 .append(input.title()) 52 .append("' validator='") 53 .append(input.volidator()) 54 .append("' class='") 55 .append(input.clazz()) 56 .append("' value='") 57 .append(value). 58 append("'>"); 59 out.write(sbf.toString()); 60 out.flush(); 61 sbf.delete(0, sbf.length()); 62 } 63 } 64 65 private String getDateString(Field field, Object bean){ 66 DateType dateType=field.getAnnotation(DateType.class); 67 String pattern=null; 68 if(dateType==null){ 69 pattern="yyyy-MM-dd"; 70 }else 71 pattern=dateType.format(); 72 field.setAccessible(true); 73 String value=null; 74 try { 75 value=DateHelper.parseString((Date)field.get(bean), pattern); 76 } catch (IllegalArgumentException e) { 77 // TODO Auto-generated catch block 78 e.printStackTrace(); 79 } catch (IllegalAccessException e) { 80 // TODO Auto-generated catch block 81 e.printStackTrace(); 82 } 83 return value; 84 } 85 86 public PrintWriter getOut() { 87 return out; 88 } 89 90 public void setOut(PrintWriter out) { 91 this.out = out; 92 } 93 94 public T getBean() { 95 return bean; 96 } 97 98 public void setBean(T bean) { 99 this.bean = bean; 100 } 101 102 103 }
最後是一個測試:
package com.fjn.tools.annotation.test; import java.io.PrintWriter; import java.util.Date; import com.fjn.tools.annotation.BeanWriter; import com.fjn.tools.annotation.Person; public class InputTest { public static void main(String[] args) { Person person=new Person(); person.setAddress("海淀西苑"); person.setAge(25); person.setName("張三"); person.setId(23); person.setBirthday(new Date()); BeanWriter<Person> inputWriter=new BeanWriter<Person>(new PrintWriter(System.out)); inputWriter.setBean(person); inputWriter.write(); } }
感興趣的朋友可以拿去執行以下這段代碼。
上面的代碼執行結果:
<input type='text' name='id' id='' style='' title='編號' validator='' class='' value='23'> <input type='text' name='name' id='' style='' title='姓名' validator='' class='' value='張三'> <input type='text' name='age' id='' style='' title='' validator='' class='' value='25'> <input type='text' name='birthday' id='' style='' title='' validator='' class='' value='2014-07-17 12:26:15'> <input type='text' name='address' id='' style='' title='' validator='' class='' value='海淀西苑'>