引言
在用
hibernate的时候发现
idea能自动生成
JavaBean,同时带有一些注解,这引起了我的好奇。当在学习
Android的时候,我发现
XUtils这个工具包中的
DBUtils也能够使用类似
hibernate的注解。于是乎在
java编程思想中找了找有关注解的用法。
一 注解定义
注解(也称为
元数据)为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便的使用这些数据。注解来源于C#之类的其他语言。注解的语法比较简单,除了
@符号外,它与java的固有语法一致。javaSE5中内置了三种注解:
@Override:定义覆盖超类,当覆写对应不上被覆盖的方法,编译器发出错误提示。
@Deprecated:当使用了该注解,即表示这个方法已经不推荐被使用。
@SuppressWarnings:关闭不当的编译器警告。
二 基本语法
我们使用自定义的注解对一个方法进行注解:
public class Testable{public void execute(){System.out.println("execute...");}@WETestvoid taskStart(){execute();}}在上边的代码中,我们对
taskStart方法使用了注解,接下来我们对
WETest注解进行定义:
import java.lang.annotation.*;@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface WETest{}三 定义注解
我们给上边的注解添加一些内容:
import java.lang.annotation.*;@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface WETest{public int id();public String Notes() default "there is no Notes";}同样,我们对Testable类使用最新的注解:
public class Testable{@WETest(id=666)public void execute(){System.out.println("execute...");}@WETest(id=666,Notes="this is a method")void taskStart(){execute();}}注解就是这么使用的,当
注解内容没有填写时,他会
使用默认的值,如execute方法,他没有定义Notes,那么Notes默认值为"there is no Notes"。
四 元注解
我们看到注解上边有两行内容,它们是元注解,专门对注解的解释。元注解一共有四种,分别是:
@Target:表示该注解可以用到哪些地方,ElementType,CONSTRUCTOR构造器声明,FIELD域声明(包括enum实例),LOCAL_VARIABLE局部变量声明,METHOD方法,PACKAGE包,PARAMETER参数,TYPE类、接口或enum。
@Retention:表示需要在什么级别上使用,RetentionPolicy,SOURCE注解会被编译器丢掉,CLASS在class文件中可用会被VM抛弃,RUNTIME在VM运行期也会保留可以通过反射获取注解信息。
@Documented:将注解包含在Javadoc中。
@Inherited:允许子类继承父类中的注解。
五 通过注解反射生成SQL语句
接下来,我用一个例子来解释注解的作用。先编写一些注解定义:
//DBTable.java用来生成数据表package annotations;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface DBTable {public String name() default "";}//Constraints.java用来定义约束项package annotations;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface Constraints {boolean primarykey() default false;boolean allownull() default true;}//PrimaryKey.java将Constraints中的primarykey定义为真,表示为主键package annotations;import java.lang.annotation.*;@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface PrimaryKey {Constraints constraints() default @Constraints(primarykey = true);}//SQLInteger.java 定义列的类型package annotations;import java.lang.annotation.*;@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface SQLInteger {String name() default "";Constraints constraints() default @Constraints;}//SQLString.java定义列的类型package annotations;import java.lang.annotation.*;@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface SQLString {int value() default 64;String name() default "";Constraints constraints() default @Constraints;} 接下来写一个javabean,使用上述注解://User.javaimport annotations.Constraints;import annotations.DBTable;import annotations.SQLInteger;import annotations.SQLString;@DBTable(name="user")public class User {@SQLInteger(name="id",constraints = @Constraints(primarykey=true))public Integer id;@SQLString(value=30)public String name;@SQLString(name="passwd",constraints=@Constraints(allownull=false))public String password;/*可以不用public void setId(Integer id) {this.id = id;}public void setName(String name) {this.name = name;}public void setPassword(String password) {this.password = password;}public Integer getId() {return id;}public String getName() {return name;}public String getPassword() {return password;}*/}我们看到注解中可以使用注解,在
SQLInteger中我们使用了Constraints注解。接下来我们写一个注解处理器:
//Test.javaimport java.lang.annotation.Annotation;import java.lang.reflect.Field;import java.util.ArrayList;import java.util.List;import java.util.Scanner;import annotations.Constraints;import annotations.DBTable;import annotations.SQLInteger;import annotations.SQLString;public class Test {public static String getConstraints(Constraints con){String constraints = "";if(!con.allownull()){constraints +=" NOT NULL";}if(con.primarykey()){constraints += " PRIMARY KEY";}return constraints;}public static void main(String[] args) throws ClassNotFoundException {Scanner s = new Scanner(System.in);String name = s.next();//从控制台输入一个类名,我们输入User即可Class<?> cl = Class.forName(name); //加载类,如果该类不在默认路径底下,会报 java.lang.ClassNotFoundExceptionDBTable dbTable = cl.getAnnotation(DBTable.class); //从User类中获取DBTable注解if(dbTable == null){ //如果没有DBTable注解,则直接返回,我们写了,当然有return;}String tableName = (dbTable.name().length()<1)?cl.getName():dbTable.name();//获取表的名字,如果没有在DBTable中定义,则获取类名作为Table的名字List<String> columnDefs = new ArrayList<String>();for(Field field : cl.getDeclaredFields())//获取声明的属性{String columnName = null;Annotation[] anns = field.getDeclaredAnnotations();//获取注解,一个属性可以有多个注解,所以是数组类型if(anns.length < 1){continue;}if(anns[0] instanceof SQLInteger)//判断注解类型{SQLInteger sInt = (SQLInteger)anns[0];columnName = (sInt.name().length()<1)?field.getName():sInt.name();//获取列名称与获取表名一样columnDefs.add(columnName+" INT"+getConstraints(sInt.constraints()));//使用一个方法,自己写的getConstraints(Constraints constraints)获取列定义}if(anns[0] instanceof SQLString){SQLString sStr = (SQLString)anns[0];columnName = (sStr.name().length()<1)?field.getName().toUpperCase():sStr.name();columnDefs.add(columnName + " VARCHAR("+sStr.value()+")"+getConstraints(sStr.constraints()));}}StringBuilder createCommand = new StringBuilder("CREATE TABLE "+tableName+"(");for(String columnDef :columnDefs){createCommand.append("
"+columnDef+",");}String tableCreate = createCommand.substring(0,createCommand.length()-1)+"
);";System.out.println(tableCreate);//打印出来}}我们可以采用上述方法动态的处理一些数据,例如创建数据表。
六 总结
注意:注解不支持继承例如 extends @xxx。 注解的default默认值不可以为null使用注解可以减少对xml等外部文件的依赖,使得对类的定义可以在一处实现,避免了一个类两处定义的麻烦。spring和hibernate就采用的这样的方法。Hibernate+JUnit测试实体类生成数据库表 http://www.linuxidc.com/Linux/2015-07/120161.htmHibernate整体理解 http://www.linuxidc.com/Linux/2014-07/104405.htmHibernate的映射机制 http://www.linuxidc.com/Linux/2014-12/110265.htm
Hibernate 的详细介绍:请点这里
Hibernate 的下载地址:请点这里
本文永久更新链接地址:http://www.linuxidc.com/Linux/2015-07/120704.htm