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