转载

怎样优雅地使用java注解

优雅的使用Java注解的前提是理解Java注解,并学习优秀的Java注解的使用demo。 注解作用:每当你创建描述符性质的类或者接口时,一旦其中包含重复性的工作,就可以考虑使用注解来简化与自动化该过程。 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<String> columnDefs = new ArrayList<String>();
            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);
   */// :~
正文到此结束
Loading...