怎样优雅地使用java注解?

注解作用:每当你创建描述符性质的类或者接口时,一旦其中包含重复性的工作,就可以考虑使用注解来简化与自动化该过程。

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);  */// :~

你可能感兴趣的:(怎样优雅地使用java注解?)