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. 一些 tips

    在本博客中,一般写题解的题都是我认为比较有价值的题,然而我还做过一些有一定价值,但并没有达到值得写一篇题解的程度,故将这些题目总结出的套路用一句话概括在这里: 当然如果看到我太久不更请在评论区里催我一 ...

  2. 莫比乌斯反演&各种筛法

    不学莫反,不学狄卷,就不能叫学过数论 事实上大概也不是没学过吧,其实上赛季头一个月我就在学这东西,然鹅当时感觉没学透,连杜教筛复杂度都不会证明,所以现在只好重新来学一遍了(/wq 真·实现了水平的负增 ...

  3. DirectX12 3D 游戏开发与实战第八章内容(上)

    8.光照 学习目标 对光照和材质的交互有基本的了解 了解局部光照和全局光照的区别 探究如何用数学来描述位于物体表面上某一点的"朝向",以此来确定入射光照射到表面的角度 学习如何正确 ...

  4. 【2】蛋白鉴定软件之Comet

    目录 1.简介 2.下载安装 3.软件使用 4.结果 1.简介 官网:http://comet-ms.sourceforge.net/ 1993年开发,持续更新,免费开源 适用Windows/Linu ...

  5. python包之drmaa:集群任务管理

    目录 1. drmaa简介 2. 安装和配置 3. 示例 3.1 开始和终止会话 3.2 运行工作 3.3 等待工作 3.4 控制工作 3.5 查询工作状态 4. 应用 4.1 写一个简单应用 4.2 ...

  6. linux—查看所有的账号以及管理账号

    用过Linux系统的人都知道,Linux系统查看用户不是会Windows那样,鼠标右键看我的电脑属性,然后看计算机用户和组即可. 那么Linux操作系统里查看所有用户该怎么办呢?用命令.其实用命令就能 ...

  7. python函数初体验

    函数 函数参数w 形式参数>>>>(被指定具体的值)默认参数, 实际参数是调用时候的实际指定参数 我们把函数⾥⾯的参数叫形式函数,函数实际调⽤的时候,赋予的参数叫实际函数 定义 ...

  8. C++ 中的多重继承的问题

    如何正确使用C++多重继承 BY R12F · PUBLISHED 2011年06月17日 · UPDATED 2012年03月11日   原创文章,转载请注明:转载自Soul Apogee本文链接地 ...

  9. Hive(一)【基本概念、安装】

    目录 一. Hive基本概念 1.1 Hive是什么 1.2 Hive的优缺点 1.3 Hive的架构 1.4 Hive和数据库的区别 二. Hive安装 2.1 安装地址 2.2 Mysql的安装 ...

  10. Spark(八)【广播变量和累加器】

    目录 一. 广播变量 使用 二. 累加器 使用 使用场景 自定义累加器 在spark程序中,当一个传递给Spark操作(例如map和reduce)的函数在远程节点上面运行时,Spark操作实际上操作的 ...