注解作用:每当你创建描述符性质的类或者接口时,一旦其中包含重复性的工作,就可以考虑使用注解来简化与自动化该过程。
Java提供了四种元注解,专门负责新注解的创建工作。
比如Junit3和Junit4 ,比如Servlet2与Servlet3 比如Hibernate3与Hibernate4 比如Spring2之后的Spring版本,都引用注解这一机制,作用就是利用注解将一些本来重复性的工作,变成程序自动完成,简化和自动化该过程(PostScript:上述各个组件我也不是很熟悉,具体加入注解的版本是几不一定正确)。
元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解:
1.@Target, 2.@Retention, 3.@Documented, 4.@Inherited
这些类型和它们所支持的类在java.lang.annotation包中可以找到。下面我们看一下每个元注解的作用和相应分参数的使用说明。
@Target
@Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。
作用:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
取值(ElementType)有:
1.CONSTRUCTOR:用于描述构造器 2.FIELD:用于描述域 3.LOCAL_VARIABLE:用于描述局部变量 4.METHOD:用于描述方法 5.PACKAGE:用于描述包 6.PARAMETER:用于描述参数 7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
例子:
Entity.java
/*** * * 实体注解接口 */@Target(value = {ElementType.TYPE}) //仅应用于类、接口、enum声明、注解类型@Retention(value = RetentionPolicy.RUNTIME) //运行时有效public @interface Entity { /*** * 实体默认firstLevelCache属性为false * @return boolean */ boolean firstLevelCache() default false; /*** * 实体默认secondLevelCache属性为false * @return boolean */ boolean secondLevelCache() default true; /*** * 表名默认为空 * @return String */ String tableName() default ""; /*** * 默认以""分割注解 */ String split() default "";}
@Retention
@Retention定义了该Annotation被保留的时间长短:某些Annotation仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中;编译在class文件中的Annotation可能会被虚拟机忽略,而另一些在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。使用这个meta-Annotation可以对 Annotation的“生命周期”限制。
作用:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
取值(RetentionPoicy)有:
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在运行时有效(即运行时保留)
/*** * 字段注解接口 */@Target(value = {ElementType.FIELD})//注解可以被添加在属性上@Retention(value = RetentionPolicy.RUNTIME)//注解保存在JVM运行时刻,能够在运行时刻通过反射API来获取到注解的信息public @interface Column { String name();//注解的name属性}
-------------------------------------分割线---------------------------------------------------------
一个完整的例子
注解:DBTable.java
package annotations.database;import java.lang.annotation.*;@Target(ElementType.TYPE) // 应用于类、接口、enum、注解类型@Retention(RetentionPolicy.RUNTIME)public @interface DBTable { public String name() default "";}
注解:Constraints.java
package annotations.database;import java.lang.annotation.*;@Target(ElementType.FIELD) //用于变量名@Retention(RetentionPolicy.RUNTIME)public @interface Constraints { boolean primaryKey() default false; boolean allowNull() default true; boolean unique() default false;}
注解:SQLString.java
package annotations.database;import java.lang.annotation.*;@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface SQLString { int value() default 0; String name() default ""; Constraints constraints() default @Constraints;}
注解:SQLInteger.java
package annotations.database;import java.lang.annotation.*;@Target(ElementType.FIELD)//FIELD 用于变量名@Retention(RetentionPolicy.RUNTIME)public @interface SQLInteger { String name() default ""; Constraints constraints() default @Constraints;}
类Member.java
package annotations.database;@DBTable(name = "MEMBER")public class Member { @SQLString(30) String firstName; @SQLString(50) String lastName; @SQLInteger Integer age; @SQLString(value = 30,constraints = @Constraints(primaryKey = true)) String handle; static int memberCount; public String getHandle() { return handle; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public String toString() { return handle; } public Integer getAge() { return age; }}
------------------------------分割线-----------------------------------
注解处理器TableCreator.java
下面是一个注解处理器的例子,它将读取一个类文件,并检查其上的数据库注解,并生成用来创建数据库的SQL命令
package com.annotation;import java.lang.annotation.Annotation;import java.lang.reflect.Field;import java.util.ArrayList;import java.util.List;import javax.swing.SpringLayout.Constraints;public class TableCreator{ public static void main(String[] args) throws Exception { if (args.length < 1) { System.out.println("arguments: annotated classes"); System.exit(0); } for (String className : args) { Class cl = Class.forName(className); DBTable dbTable = cl.getAnnotation(DBTable.class); if (dbTable == null) { System.out.println("No DBTable annotations in class " + className); continue; } String tableName = dbTable.name(); // If the name is empty, use the Class name: if (tableName.length() < 1) tableName = cl.getName().toUpperCase(); List columnDefs = new ArrayList(); for (Field field : cl.getDeclaredFields()) { String columnName = null; Annotation[] anns = field.getDeclaredAnnotations(); if (anns.length < 1) continue; // Not a db table column if (anns[0] instanceof SQLInteger) { SQLInteger sInt = (SQLInteger) anns[0]; // Use field name if name not specified if (sInt.name().length() < 1) columnName = field.getName().toUpperCase(); else columnName = sInt.name(); columnDefs.add(columnName + " INT" + getConstraints(sInt.constraints())); } if (anns[0] instanceof SQLString) { SQLString sString = (SQLString) anns[0]; // Use field name if name not specified. if (sString.name().length() < 1) columnName = field.getName().toUpperCase(); else columnName = sString.name(); columnDefs.add(columnName + " VARCHAR(" + sString.value() + ")" + getConstraints(sString.constraints())); } StringBuilder createCommand = new StringBuilder("CREATE TABLE " + tableName + "("); for (String columnDef : columnDefs) createCommand.append("\n " + columnDef + ","); // Remove trailing comma String tableCreate = createCommand.substring(0, createCommand.length() - 1) + ");"; System.out.println("Table Creation SQL for " + className + " is :\n" + tableCreate); } } } private static String getConstraints(Constraints con) { String constraints = ""; if (!con.allowNull()) constraints += " NOT NULL"; if (con.primaryKey()) constraints += " PRIMARY KEY"; if (con.unique()) constraints += " UNIQUE"; return constraints; }} /* * Output: Table Creation SQL for annotations.database.Member is : CREATE * TABLE MEMBER( FIRSTNAME VARCHAR(30)); Table Creation SQL for * annotations.database.Member is : CREATE TABLE MEMBER( FIRSTNAME * VARCHAR(30), LASTNAME VARCHAR(50)); Table Creation SQL for * annotations.database.Member is : CREATE TABLE MEMBER( FIRSTNAME * VARCHAR(30), LASTNAME VARCHAR(50), AGE INT); Table Creation SQL for * annotations.database.Member is : CREATE TABLE MEMBER( FIRSTNAME * VARCHAR(30), LASTNAME VARCHAR(50), AGE INT, HANDLE VARCHAR(30) PRIMARY * KEY); */// :~