一 点睛
1 APT简介
APT(annotation processing tool)是一种处理注释的工具,它对源代码文件进行检测找出其中的Annotation后,对Annotation进行额外的处理。
Annotation处理器在处理Annotation时可以根据源文件中的Annotation生成额外的源文件和其它的文件(文件具体内容由Annotation处理器的编写者决定),APT还会编译生成的源代码文件和原来的源文件,将它们一起生成class文件。
2 用户开发自定义APT
为了使用系统的APT工具来读取源文件中的Annotation,程序员必须自定义一个Annotation处理器,编写Annotation处理器需要使用JDK lib目录中的tools.jar里的如下4个包:
-
com.sun.mirror.apt:和APT交互的接口。
-
com.sun.mirror.declaration:包含各种封装类成员、类方法、类声明的接口。
-
com.sun.mirror.type:包含各种封装源代码中程序元素的接口。
-
com.sun.mirror.util:提供了用于处理类型和声明的一些工具。
二 实战——自定义Hibernate的APT
1 Persistent定义关于表的注解
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
@Documented
public @interface Persistent
{
String table();
}
2 Id定义关于表id的注解
import java.lang.annotation.*;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.SOURCE)
@Documented
public @interface Id
{
String column();
String type();
String generator();
}
3 Property定义关于表的属性注解
import java.lang.annotation.*;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.SOURCE)
@Documented
public @interface Property
{
String column();
String type();
}
4 需要处理的实体类
@Persistent(table="person_inf")
public class Person
{
@Id(column="person_id",type="integer",generator="identity")
private int id;
@Property(column="person_name",type="string")
private String name;
@Property(column="person_age",type="integer")
private int age;
//无参数的构造器
public Person()
{
}
//初始化全部成员变量的构造器
public Person(int id , String name , int age)
{
this.id = id;
this.name = name;
this.age = age;
}
// 下面省略所有成员变量的setter和getter方法
//id的setter和getter方法
public void setId(int id)
{
this.id = id;
}
public int getId()
{
return this.id;
}
//name的setter和getter方法
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return this.name;
}
//age的setter和getter方法
public void setAge(int age)
{
this.age = age;
}
public int getAge()
{
return this.age;
}
}
5 自定义Hibernate的APT
import javax.annotation.processing.*;
import javax.lang.model.element.*;
import javax.lang.model.*;
import java.io.*;
import java.util.*;
@SupportedSourceVersion(SourceVersion.RELEASE_8)
// 指定可处理@Persistent、@Id、@Property三个Annotation
@SupportedAnnotationTypes({"Persistent" , "Id" , "Property"})
public class HibernateAnnotationProcessor
extends AbstractProcessor
{
// 循环处理每个需要处理的程序对象
public boolean process(Set<? extends TypeElement> annotations
, RoundEnvironment roundEnv)
{
// 定义一个文件输出流,用于生成额外的文件
PrintStream ps = null;
try
{
// 遍历每个被@Persistent修饰的class文件
for (Element t : roundEnv.getElementsAnnotatedWith(Persistent.class))
{
// 获取正在处理的类名
Name clazzName = t.getSimpleName();
// 获取类定义前的@Persistent Annotation
Persistent per = t.getAnnotation(Persistent.class);
// 创建文件输出流
ps = new PrintStream(new FileOutputStream(clazzName
+ ".hbm.xml"));
// 执行输出
ps.println("<?xml version=\"1.0\"?>");
ps.println("<!DOCTYPE hibernate-mapping PUBLIC");
ps.println(" \"-//Hibernate/Hibernate "
+ "Mapping DTD 3.0//EN\"");
ps.println(" \"http://www.hibernate.org/dtd/"
+ "hibernate-mapping-3.0.dtd\">");
ps.println("<hibernate-mapping>");
ps.print(" <class name=\"" + t);
// 输出per的table()的值
ps.println("\" table=\"" + per.table() + "\">");
for (Element f : t.getEnclosedElements())
{
// 只处理成员变量上的Annotation
if (f.getKind() == ElementKind.FIELD) // ①
{
// 获取成员变量定义前的@Id Annotation
Id id = f.getAnnotation(Id.class); // ②
// 当@Id Annotation存在时输出<id.../>元素
if(id != null)
{
ps.println(" <id name=\""
+ f.getSimpleName()
+ "\" column=\"" + id.column()
+ "\" type=\"" + id.type()
+ "\">");
ps.println(" <generator class=\""
+ id.generator() + "\"/>");
ps.println(" </id>");
}
// 获取成员变量定义前的@Property Annotation
Property p = f.getAnnotation(Property.class); // ③
// 当@Property Annotation存在时输出<property.../>元素
if (p != null)
{
ps.println(" <property name=\""
+ f.getSimpleName()
+ "\" column=\"" + p.column()
+ "\" type=\"" + p.type()
+ "\"/>");
}
}
}
ps.println(" </class>");
ps.println("</hibernate-mapping>");
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
finally
{
if (ps != null)
{
try
{
ps.close();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
return true;
}
}
三 运行
E:\Java\疯狂java讲义\codes\14\14.4>javac -processor HibernateAnnotationProcessor Persistent.java
四 生成的XML文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Person" table="person_inf">
<id name="id" column="person_id" type="integer">
<generator class="identity"/>
</id>
<property name="name" column="person_name" type="string"/>
<property name="age" column="person_age" type="integer"/>
</class>
</hibernate-mapping>

374

被折叠的 条评论
为什么被折叠?



