APT的介绍:

APT(Annotation Processing Tool)是一种注解处理工具,它对源代码文件进行检测,并找出源文件所包含的注解信息,然后针对注解信息进行额外的处理。
使用APT工具处理注解时可以根据源文件中的注解生成额外的源文件和其他的文件(文件的具体内容由注解处理器的编写者决定),APT还会编译生成的源代码文件和原来的源文件,将它们一起生成class文件。

Hibernate自动生成XML模拟:

涉及知识点:

1、自定义注释使用原注释

@Target(ElementType.FIELD) //只能修饰变量,属性
@Retention(RetentionPolicy.SOURCE) // 保留在源代码中,编译时丢弃
2、自定义注解处理类,继承注解处理工具类javax.annotation.processing.AbstractProcessor重写抽象方法process 处理注解
    • 形参RoundEnvironment类型的形参roundEnvironment接收被处理的类.java源文件
    • getElementsAnnotatedWith(注解类.class)方法 获取被注解修饰的元素Element 的Set集合
    • 遍历集合中Element元素
    • 通过集合元素Element对象getEnclosedElements方法获取Element直接包含的子元素Element
    • 元素的getKind()方法获取元素类型,其中ElementKind.FIELD表示成员变量
    • Element.getAnnotation(注解类.class) 方法获取对应元素的实际注解,不存在则返回null
3、文件读写
    • 字符流BufferedWriter(new FileWriter())
    • 字符串StringBuilder和StringBuffer 节省内存
在早期Hibernate版本中,每写一个Java类文件,还必须额外地维护Hibemate映射文件(名为*.hbm.xml的文件,也有一些工具可以自动生成),下面我们使用注解来模拟简化操作。
TODO:
首先定义要生成Xml需要的三个注解:
1、用于修饰一个类的注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
* @ClassName Presistent
* @projectName: object1
* @author: Zhangmingda
* @description: 该注解用来修饰数据库一个表
* date: 2021/5/19.
*/
@Target(ElementType.TYPE) //只能修饰类、接口(包括注解类型)或枚举定义
@Retention(RetentionPolicy.SOURCE) //注解只保留在源代码中,编译器直接丢弃这种注解
public @interface Presistent {
String table();
}

2、用于修饰类中属性(变量) 的两个注解

 用于标识这是个表格id字段

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
* @ClassName Id
* @projectName: object1
* @author: Zhangmingda
* @description: 用来修饰字段是否为ID字段,以及特征属性
* date: 2021/5/19.
*/
@Target(ElementType.FIELD) //只能修饰变量(属性)
@Retention(RetentionPolicy.SOURCE) // 只保留在源代码中,编译的时候丢弃
public @interface Id {
String column();
String type();
String generator();
}

用于标识该字段的字段名和字段类型

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
* @ClassName Property
* @projectName: object1
* @author: Zhangmingda
* @description: 用来修饰普通字段性质
* date: 2021/5/19.
*/
@Target(ElementType.FIELD) //只能修饰变量,属性
@Retention(RetentionPolicy.SOURCE) // 保留在源代码中,编译时丢弃
public @interface Property {
String column();
String type();
}

3、编写编译注解处理工具类

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
import java.util.Set; /**
* @ClassName Apt
* @projectName: object1
* @author: Zhangmingda
* @description: 注解处理工具类继承AbstractProcessor
* date: 2021/5/19.
*/ @SupportedSourceVersion(SourceVersion.RELEASE_11) //支持的最新java版本
@SupportedAnnotationTypes({"Presistent","Property","Id"}) //可以处理的注解类型
public class Apt extends AbstractProcessor {
/**
* 该方法在命令行 java -processor Apt (本类类名) User.java时会自动执行
* @param set
* @param roundEnvironment
* @return
*/
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
//获取Presistent注解修饰的类
Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(Presistent.class);
//遍历被修饰的类名,注解进行处理
for (Element element: elements){
//获取javax.lang.model.element.Name类名
Name className = element.getSimpleName();
//获取注解对象
Presistent presistent = element.getAnnotation(Presistent.class);
/**
* 创建我们对应的xml文件
*/
try (BufferedWriter bw = new BufferedWriter(new FileWriter(className + "hbm.xml"))){
System.out.println();
//初始字符串初始化
StringBuilder stringBuilder = new StringBuilder("<?xml version=\"1.0\"?>\n<!DOCTYPE hibernate-mapping PUBLIC\n\t\"-//Hibernate/Hibernate Mapping DTD 3.0//EN\"\n\t\"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd\">\n");
stringBuilder.append("<hibernate-mapping>\n");
//表格维度数据
stringBuilder.append("\t<class name=\"" + className + "\" table=\"" + presistent.table() + "\">\n"); //字段维度//获取所有直接包含的元素
List<? extends Element> fElements = element.getEnclosedElements();
//对所有元素判断是否被对应注解修饰,所有修饰的都处理
for (Element fElement: fElements){ //获取元素种类,如果判断为成员变量,做处理
if (fElement.getKind() == ElementKind.FIELD){ //获取成员变量上的注解
//判断否是ID注解修饰
Id id = fElement.getAnnotation(Id.class);
Property property = fElement.getAnnotation(Property.class);
if (id != null){
System.out.println(id);
System.out.println(fElement.getSimpleName());
stringBuilder.append("\t\t<id name=\"" + fElement.getSimpleName() + "\" column=\"" + id.column() + "\" type=\"" + id.type() + "\">\n");
stringBuilder.append("\t\t\t<generator class=\"" + id.generator() + "\"/>\n");
stringBuilder.append("\t\t</id>\n");
}
if (property != null){
System.out.println(property);
System.out.println(fElement.getSimpleName());
stringBuilder.append("\t\t<property name=\"" + fElement.getSimpleName() + "\" column=\"" + property.column() + "\" type=\"" + property.type() + "\"/>\n");
}
}
} //表格维度结束
stringBuilder.append("\t</class>\n");
stringBuilder.append("</hibernate-mapping>");
//写入文件
bw.write(stringBuilder.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
}

4、数据库User表类

表类用Presistent注解修饰,字段用Id 和Property 注解修饰

/**
* @ClassName User
* @projectName: object1
* @author: Zhangmingda
* @description: 用于生成XML文本的对象,只获取经过修饰符修饰的对象
* date: 2021/5/19.
*/
@Presistent(table = "user")
public class User {
@Id(column = "id", type = "int", generator = "auto")
private int id; @Property(column = "name", type = "varchar")
private String name; @Property(column = "age", type = "varchar")
private String age; public User(int id, String name, String age) {
this.id = id;
this.name = name;
this.age = age;
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getAge() {
return age;
} public void setAge(String age) {
this.age = age;
}
}

用法:IDEA的CMD命令行执行

  • 1、javac -encoding utf-8 Apt.java 编译注解处理工具类
  • 2、javac -encoding utf-8 -processor Apt User.java 使用注解处理类处理表类,生成xml文件

 查看生成的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="User" table="user">
<id name="id" column="id" type="int">
<generator class="auto"/>
</id>
<property name="name" column="name" type="varchar"/>
<property name="age" column="age" type="varchar"/>
</class>
</hibernate-mapping>

java 编程基础:注解(Annotation Processing Tool)注解处理器 利用注解解读类属性生成XML文件的更多相关文章

  1. java 编程基础:注解的功能和作用,自定义注解

    1,什么是注解: 从JDK5开始,Java增加了对元数据 (MetaData)的支持,也就是Annotation注解,这种注解与注释不一样,注解其实是代码里的特殊标记,这些标记可以在编译.类加载 运行 ...

  2. Java入门——(1)Java编程基础

    Java入门--(1)Java编程基础 第二章 Java编程基础   JAVA 代码的基本格式: 修饰符 class 类名{ 程序代码 }   2.1关键字:赋予了特殊含义的单词.   2.2标识符: ...

  3. Bean 注解(Annotation)配置(1)- 通过注解加载Bean

    Spring 系列教程 Spring 框架介绍 Spring 框架模块 Spring开发环境搭建(Eclipse) 创建一个简单的Spring应用 Spring 控制反转容器(Inversion of ...

  4. Java开发知识之Java编程基础

    Java开发知识之Java编程基础 一丶Java的基础语法 每个语言都有自己的语法规范.例如C++ 入口点是main. 我们按照特定格式编写即可. Java也不例外. Java程序的语法规范就是 Ja ...

  5. java编程基础二进制

    0.java编程基础 01.二进制(原码,反码,补码) 02.位运算 03.移位运算符 二进制 原码,反码,补码 1.基本概念 二进制是逢2进位的进位制,0,1是基本算符. 现在的电子计算机技术全部使 ...

  6. Java编程基础-面向对象(中)

    本章承接Java编程基础-面向对象(上)一文. 一.static关键字 在java中,定义了一个static关键字,它用于修饰类的成员,如成员变量.成员方法以及代码块等,被static修饰的成员具备一 ...

  7. Java编程基础——数组和二维数组

    Java编程基础——数组和二维数组 摘要:本文主要对数组和二维数组进行简要介绍. 数组 定义 数组可以理解成保存一组数的容器,而变量可以理解为保存一个数的容器. 数组是一种引用类型,用于保存一组相同类 ...

  8. Java编程基础——流程控制

    Java编程基础——流程控制 摘要:本文主要介绍Java编程中的流程控制语句. 分类 流程控制指的是在程序运行的过程中控制程序运行走向的方式.主要分为以下三种: 顺序结构:从上到下依次执行每条语句操作 ...

  9. Java编程基础——运算符和进制

    Java编程基础——运算符和进制 摘要:本文主要介绍运算符和进制的基本知识. 说明 分类 Java语言支持如下运算符: ◆ 算术运算符:++,--,+,-,*,/,%. ◆ 赋值运算符:=,+=,-= ...

随机推荐

  1. redis可以设置过期key回调实现延时队列

    <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring- ...

  2. html+css第六篇-定位

    relative相对定位/定位偏移量 position:relative; 相对定位 a.不影响元素本身的特性: b.不使元素脱离文档流: c.如果没有定位偏移量,对元素本身没有任何影响: 定位元素位 ...

  3. Python描述符以及Property方法的实现原理

    Python描述符以及Property方法的实现原理 描述符的定义: 描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实了__get__(),__set__(),__delete__()中 ...

  4. CF1444C Team-Building

    考虑我们判定二分图染色的经典算法: 染色. 我们把所有不同颜色块之间的边都保存下来. 只在图中保留相同颜块之间的边,并对其染色. 我们考虑记\(g_i\)为一个点的所在联通块编号,\(f_i\)为他在 ...

  5. Codeforces 1063F - String Journey(后缀数组+线段树+dp)

    Codeforces 题面传送门 & 洛谷题面传送门 神仙题,做了我整整 2.5h,写篇题解纪念下逝去的中午 后排膜拜 1 年前就独立切掉此题的 ymx,我在 2021 年的第 5270 个小 ...

  6. 监听浏览器tab切换

    监听浏览器切屏 为了完成验证用户在切换浏览器tab时进行登录再次认证需求需要监听浏览器切换窗口 if (document.hidden !== undefined) { document.addEve ...

  7. 如何反向推断基因型文件中的参考碱基(REF/ALT)?

    目录 需求 解决 方法一 方法二 需求 客户随手丢来一个基因型文件,类似于hapmap格式,只是少了中间多余的那几列,像这种类hapmap格式文件,往往是芯片数据. 这样的数据因为缺乏等位基因:参考碱 ...

  8. R语言与医学统计图形【6】低级绘图函数

    R语言基础绘图系统 基础绘图包之低级绘图函数--定义坐标轴.图例.文本 低级绘图函数:本身不具备图形绘制能力,只是在已有图形基础上添加元素. 函数 功能 arrows 添加箭头 axis 坐标轴 bo ...

  9. Linux—yum的python版本错误——高级解决方案

    彻底搞明白,python升级后,为什么会导致yum不可用 首先我们来分析下,python升级后,yum为什么会不可用? 先说个关于python的问题,Linux系统很多软件都依赖于python,因此不 ...

  10. 用jquery的prop方法操作checkbox

    prop设置checkbox选中 $('#checkbox-id').prop("checked",true) 判断checkbox是否选中,if ($('#checkbox-id ...