java痛苦學習之路[九]---Java Annotation

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)   //接口、類、枚舉、註解

@Target(ElementType.FIELD) //字段、枚舉的常量
@Target(ElementType.METHOD) //方法
@Target(ElementType.PARAMETER) //方法參數
@Target(ElementType.CONSTRUCTOR)  //構造函數
@Target(ElementType.LOCAL_VARIABLE)//局部變量
@Target(ElementType.ANNOTATION_TYPE)//註解
@Target(ElementType.PACKAGE) ///包   

@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='海淀西苑'>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章