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. Python+selenium定位一组元素,复选框

  2. 描述高频题之队列&栈

    栈和队列 全文概览 基础知识 栈 栈是一种先进后出的数据结构.这里有一个非常典型的例子,就是堆叠盘子.我们在放盘子的时候,只能从下往上一个一个的放:在取的时候,只能从上往下一个一个取,不能从中间随意取 ...

  3. 洛谷 P7516 - [省选联考 2021 A/B 卷] 图函数(Floyd)

    洛谷题面传送门 一道需要发现一些简单的性质的中档题(不过可能这道题放在省选 D1T3 中偏简单了?) u1s1 现在已经是 \(1\text{s}\)​ \(10^9\)​ 的时代了吗?落伍了落伍了/ ...

  4. Atcoder Grand Contest 020 E - Encoding Subsets(记忆化搜索+复杂度分析)

    Atcoder 题面传送门 & 洛谷题面传送门 首先先考虑如果没有什么子集的限制怎样计算方案数.明显就是一个区间 \(dp\),这个恰好一年前就做过类似的题目了.我们设 \(f_{l,r}\) ...

  5. 关于 n 个 [0,1] 的随机变量第 k 小的期望值

    今天做到一道题,感觉里面一个结论有点意思,就到网上扒了篇证明(bushi)下来了. 知乎回答习惯,先抛结论,再给证明(大雾 结论:对于 \(n\) 个取值范围为 \([0,1]\) 的随机变量 \(x ...

  6. 自定义 Word 模板

    自定义 Word 模板 目录 必要设置 样式设置 标题样式 多级列表 封面 正文 引用目录 页码 页眉 图标 自定义模板保存 样式导入和导出 批量删除多余空白段落 必要设置 显示所有格式标记 选择&q ...

  7. 第二个基础框架 — spring — xml版,没用注解 — 更新完毕

    1.什么是spring? 老规矩:百度百科一手 这上面说得太多了,我来提炼一下: spring就是一个轻量级的控制反转( IOC ) 和 面向切面编程( AOP ) 的容量框架.总的来说:本质就是对j ...

  8. 用python写的推箱子搜索程序

    1 # -*- coding: gbk -*- 2 from functools import reduce 3 from copy import deepcopy 4 import re 5 def ...

  9. Shell学习(九)——chattr与lsattr命令详解

    有时候你发现用root权限都不能修改某个文件,大部分原因是曾经用chattr命令锁定该文件了.chattr命令的作用很大,其中一些功能是由Linux内核版本来支持的,不过现在生产绝大部分跑的linux ...

  10. swift设置导航栏item颜色和状态栏颜色

    //swift设置导航栏item颜色和状态栏颜色 let dict:Dictionary =[NSForegroundColorAttributeName:UIColor.hrgb("333 ...