使用JAnnocessor生成Java代码

在本文中,我将向你展示如何生成的代码JAnnocessor通过创建框架Nikolche Mihajlovski 。 在Nikolche的演讲中,我第一次在GeeCON 2012大会上遇到JAnnocessor: “创新和实用的Java源代码生成” (幻灯片) 。 之后,我在一个项目中成功使用了它。 这个框架几乎没有资源,所以我希望我的文章对那些对使用它感兴趣或正在为项目寻找全新玩具的人有所帮助。

背景

每个Java开发人员每天都使用某种代码生成工具。 设置器,获取器,琐碎的构造函数,toString –所有这些只是样板代码。 通常,我们会在我们最喜欢的IDE的帮助下生成它。 我真的无法想象手动编码它,并且由于Java是一种静态语言,我们将永远无法跳过此过程。

所有现代IDE都提供的那些琐碎的代码生成示例并不是唯一有用的代码生成情况。 有许多现代框架生成一些代码来帮助我们编写更可靠的代码并更快地执行。 我认为最著名的示例是QueryDSL和JPA2元模型生成器 ,它们创建用于执行类型安全的数据库查询的对象。

还有其他情况-IDE不能很好地支持-我们可以使用代码生成。 通常,它可能有助于生成:

  • 建造者
  • 正面
  • 从域对象到DTO的DTO和映射器

这些仅是示例。 对于某些项目,可能存在某些特定于项目的项目,我们不能使用任何现有的代码生成工具,而必须编写自己的代码。 怎么做? 使用Java APT –注释处理工具 。

关于Java APT的几句话

Java 1.5中引入了注释处理工具,它提供了用于处理注释类的低级API。 它是大多数(也许是全部?)现有代码生成框架的基础,并且由于API的级别很低,如果您只想生成一些类,我不建议您使用纯Java APT。 使用apt-jelly(另一个代码生成工具)页面上的示例 ,可以很清楚地了解使用APT进行代码生成的情况。

您可以使用现有框架之一,而不必使用普通的Java APT。 最近,我参加了有关有趣的JAnnocessor的会议讨论,该JAnnocessor似乎做得很好。

您好JAnnocessor

JAnnocessor是Nikolche Mihajlovski制作的一个相当新的框架。 与APT有何不同? 这是作者怎么说的作者:

JAnnocessor建立在Java APT的基础上,将Java源代码模型封装在丰富而方便的高级域模型中,该模型是表达匹配和转换的良好目标。

JAnnocessor带有几个内置处理器: builderdtofacademapper 。 如果您需要自定义功能,则可以轻松地自己编写。

有一个很大的缺点–非常差的文档。 实际上,几乎没有任何文档。 在Wiki中,您找不到太多甚至更糟的东西–在框架类中也找不到Javadocs。 尽管有作者编写的入门指南 ,但我还是有一些遗漏之处,因此我将逐步指导您完成基础知识。  

Maven设置

我们将仅在编译阶段使用JAnnocessor,因此无需将其添加到我们的应用程序包中-我们将范围设置为

<dependency><groupId>com.googlecode.jannocessor</groupId><artifactId>jannocessor</artifactId><version>0.7.2</version><scope>provided</scope>
</dependency>

下一部分是注释处理插件。 尽管《 入门指南》建议使用jannocessor-maven-plugin,但由于缺少一些配置选项,我被迫使用maven-processor-plugin“过时”。

在构建/插件部分,我们添加:

<plugin><groupId>org.bsc.maven</groupId><artifactId>maven-processor-plugin</artifactId><version>2.0.4</version><executions><execution><id>generate-code</id><goals><goal>process</goal></goals><phase>compile</phase><configuration><processors><processor>org.jannocessor.processor.JannocessorProcessor</processor></processors><systemProperties><logback.configurationFile>${project.basedir}/etc/jannocessor-logback.xml</logback.configurationFile></systemProperties><options><templates.path>${project.basedir}/src/main/resources</templates.path></options><defaultOutputDirectory>${project.basedir}/target/generated-sources/</defaultOutputDirectory></configuration></execution></executions>
</plugin>
  • 处理器 -告诉maven-processor-plugin哪个类执行注释处理-请勿更改
  • configuration / logback.configurationFile –是可选的。 JAnnocessor使用内部lo​​gback进行日志记录,如果您在项目中也这样做,并且在classpath中有logback.xml,它将由JAnnocessor使用。 我建议为JAnnocessor编写单独的日志记录配置,以避免可能的问题(例如,如果您使用janino conditionals )。 jannocessor-logback.xml可以很简单:
    <?xml version="1.0" encoding="UTF-8"?>
    <configuration><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%-30(%date) %-5level %logger{0} %msg%n</pattern></encoder></appender><root level="error"><appender-ref ref="console"/></root></configuration>
  • options / templates.path –可能您将使用自定义JAnnocessor模板。 如果您不愿意,可以删除该行
  • defaultOutputDirectory –很重要–默认情况下,将生成的类添加到src / main / java中-在我看来,这是一个非常糟糕的主意。 请记住, 每次Maven构建都会重新创建所有生成的类,并且所有手工修改都将丢失 。 这就是为什么生成的类应该放在/target/generated-sources//target/generated-test-sources/

建造者一代

在此示例中,我将使用内置生成器为我的简单POJO生成生成器类。

首先,我们需要新的注释来标记要为其生成构建器的类。 它可以很简单:

package pl.maciejwalkowiak.jannocessor.domain;public @interface GenerateBuilder {
}

我们的样本POJO:

package pl.maciejwalkowiak.jannocessor.domain;@GenerateBuilder
public class Person {private String firstName;private String lastName;private Integer age;public String getFirstName() {return firstName;}public void setFirstName(String firstName) {this.firstName = firstName;}public String getLastName() {return lastName;}public void setLastName(String lastName) {this.lastName = lastName;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}
}

接下来的重要部分是告诉JAnnocessor必须生成什么。 为此,我们需要在特定的包中创建特定的类: org.jannocessor.config.Processors 。 我找不到使它可配置的方法,这样配置就可以在我们项目的程序包中。

在配置中,我们指定应在何处放置创建的类: pl.maciejwalkowiak.jannocessor.domain.builder以及基本bean类在哪里: pl.maciejwalkowiak.jannocessor.domain 。 最后一个参数表示我们是否要使用调试模式–目前并不重要。

package org.jannocessor.config;import pl.maciejwalkowiak.jannocessor.domain.GenerateBuilder;import org.jannocessor.extra.processor.BuilderGenerator;
import org.jannocessor.model.structure.JavaClass;
import org.jannocessor.processor.annotation.Annotated;
import org.jannocessor.processor.annotation.Types;public class Processors {@Annotated(GenerateBuilder.class)@Types(JavaClass.class)public BuilderGenerator generateBuilder() {return new BuilderGenerator("pl.maciejwalkowiak.jannocessor.domain.builder", "pl.maciejwalkowiak.jannocessor.domain", false);}
}

运行它

为了运行它,我们只需要执行mvn compile 。 在target/generated-sources/pl/maciejwalkowiak/jannocessor/domain/builder/我们将找到PersonBuilder类:

package pl.maciejwalkowiak.jannocessor.domain.builder;import pl.maciejwalkowiak.jannocessor.domain.Person;
import javax.annotation.Generated;/*** Generated by JAnnocessor*/
@Generated("Easily with JAnnocessor")
public class PersonBuilder {private String firstName;private String lastName;private Integer age;public PersonBuilder firstName(String firstName) {this.firstName = firstName;return this;}public PersonBuilder lastName(String lastName) {this.lastName = lastName;return this;}public PersonBuilder age(Integer age) {this.age = age;return this;}public Person build() {Person instance = new Person();instance.setFirstName(firstName);instance.setLastName(lastName);instance.setAge(age);return instance;}}

多亏了builder类,我们有了用于创建Person对象的流畅接口:

Person person = new PersonBuilder().firstName("John").lastName("Doe").age(25).build();

创建我们自己的发电机

为了创建自定义生成器,JAnnocessor提供了丰富的API和几个示例。 不幸的是,没有可用的指南或教程。 对于本文,我想快速编写FEST Assert 2.x的生成器,但是在研究JAnnocessor源代码一段时间后,我放弃了。 相反,我将仅展示概念。

为了编写自定义生成器代码,您只需要创建从org.jannocessor.extra.processor.AbstractGenerator继承的类。

public class MyCustomGenerator extends AbstractGenerator<AbstractJavaClass> {public MyCustomGenerator(String destPackage, boolean inDebugMode) {super(destPackage, inDebugMode);}@Overrideprotected void generateCodeFrom(PowerList<AbstractJavaClass> models, ProcessingContext context) {// ....}
}

PowerList<AbstractJavaClass> models表示所有带有自定义注释的类的集合。 然后,您可以访问所有类的字段,方法,已实现的接口等。我唯一想念的就是对类超类的丰富访问。 为了获得超类的字段,我不得不使用Java Reflection API。

如果您想编写自定义生成器,我鼓励您看一下诸如BuilderGenerator之类的示例 。 数量不多,但绝对有帮助。  

摘要

在这篇文章中,我展示了如何设置和使用JAnnocessor。 尽管我认为它很好而且可能非常有用的库,但是缺少文档使其无法在真正的严肃项目中使用。 我希望Nikolche能够撰写出色的文档或围绕将要实现的项目建立社区。 我也希望该项目将移至github。 它以某种方式成为标准,因此如果作者希望围绕它建立社区–我认为这是唯一正确的举动。 尽管如此,我还是问了他这个问题,至少到目前为止,他没有任何计划。

参考: Software Development Journey博客上的JCG合作伙伴 Maciej Walkowiak 使用JAnnocessor进行Java代码生成 。


翻译自: https://www.javacodegeeks.com/2012/08/java-code-generation-with-jannocessor.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/372151.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linq学习笔记(转)

开始Linq前你要知道的 扩展方法 顾名思义就是对现有类进行扩展的的方法&#xff0c;扩展方法可以在不修改现有类的情况下&#xff0c;为现有类增加公共的接口&#xff08;不是C#中的interface&#xff09;。 扩展方法本质上是一个静态方法&#xff0c;不同之处在于它的第一个参…

cass展点不在原位置,cass中打开一副图后,通过绘图处理-——展高程点,怎么之前的图形就不显示了,,只剩下高程点!!...

答&#xff1a;1、进入控制面板&#xff0c;选择“卸载或更改程序”。 2、选中“AutoCAD2006”图标。 3、右击选择“更改”。 4、进入“AutoCAD2006安装程序对话框”&#xff0c;选择“添加/删除功能”单选按钮&#xff0c;点击下一步。 5、在“程序文件”列表中&#xff0c;选…

(二)windows下安装PHPCMS V9

一、准备工作 搭建环境 &#xff1a;参考:Windows下搭建PHP开发环境及相关注意事项PHPCMS V9 &#xff1a;下载适合自己 PHPCMS V9 版本到本地或服务器&#xff0c;下载地址&#xff1a;http://www.phpcms.cn/html/download/说明&#xff1a;官方提供了 2 种不同的编码。包括 G…

JavaFX 2.0布局窗格– HBox和VBox

如果要对JavaFX 2.0中所有不同的布局窗格进行概述&#xff0c;或者想了解有关它们的一些基本知识&#xff0c;请参阅我以前的文章《 JavaFX 2.0中的布局窗格》 。 布局窗格HBox和VBox绝对是JavaFX 2.0中最基本的布局容器。 如您所知&#xff0c;它们的用途是将所有子级布置在一…

flask mysql分页,Flask分页的实现方法

所需环境Flask-SQLAlchemy分页使用Flask-SQLAlchemy提供的pagination()方法。页数是pagination()方法的第一个参数&#xff0c;也是唯一必须的参数。可选参数per_page用来指定每页显示的记录数。参考代码&#xff1a;def index():# ...page request.args.get(page, 1, typeint…

Java中的生成器设计模式

Java 中的 Builder设计模式是一种创建模式&#xff0c;即用于创建对象&#xff0c;类似于 工厂方法设计模式 &#xff0c;这也是创建设计模式。 在学习任何设计模式之前&#xff0c;我建议先找出特定设计模式要解决的问题。 众所周知&#xff0c; 必要性是发明的母亲。 在没有面…

验证码( 随机数)

方式一&#xff08;变色版&#xff09;&#xff1a; <html> <head><meta charset"UTF-8"/><title></title><script src"jquery-2.0.2.min.js"></script> </head> <body> <?php header("co…

单片机串行通信全解析

1.什么是串行通信&#xff1f; 串行通信&#xff08;英语&#xff1a;Serial communication&#xff09;是指在计算机总线或其他数据通道上&#xff0c;每次传输一个位元数据&#xff0c;并连续进行以上单次过程的通信方式。与之对应的是并行通信&#xff0c;它在串行端口上通过…

java type 类型,java中的泛型类型与Type接口

假设我们定义了一个Room的类&#xff0c;表示一个房间public classRoom(){}由于我们建造好房间是&#xff0c;不知道房间以后的用途&#xff0c;他可能用来住人&#xff0c;也有可能用来放货物&#xff0c;因此需要用到泛型。但是我们可能想获取Room这个房间里面进来的的东西的…

centos7下操作防火墙

引言 最近使用centos7系统比较频繁&#xff0c;在配置服务器的时候&#xff0c;总是遇到能够ping通服务器&#xff0c;但是就是没有办法访问80端口&#xff0c;这个时候我的直觉告诉我&#xff0c;肯定是防火墙的原因&#xff0c;但是使用iptables却怎么都找不到命令&#xff0…

其他团队对本团队评价的总结

我们小组在看了其他小组的评价后&#xff0c;对自己的程序有了新的看法。转载于:https://www.cnblogs.com/bk1246788/p/6879691.html

Java:使用Fork / Join框架的Mergesort

此项的目的是显示一个Fork / Join RecursiveAction的简单示例&#xff0c;而不是过多地研究合并合并的可能优化方法&#xff0c;或者比使用Exkutor / Join Pool优于现有的基于Java 6的现有实现&#xff08;例如ExecutorService&#xff09;的相对优势。 以下是使用Java的自上而…

php的异常处理方式,php异常处理基本方法

当一个php脚本运行时&#xff0c;为了防止脚本运行崩溃&#xff0c;亦或是当php作为webserver&#xff0c;为了防止php程序出错&#xff0c;抛出httpcode500错误&#xff0c;我们常常需要对php程序做异常处理。今天介绍的是最基本的异常处理方法&#xff1a;一般而言&#xff0…

关系型数据库的三范式

第一范式:确保每列的原子性. 如果每列(或者每个属性)都是不可再分的最小数据单元(也称为最小的原子单元),则满足第一范式. 例如:顾客表(姓名、编号、地址、……)其中"地址"列还可以细分为国家、省、市、区等。第二范式:在第一范式的基础上更进一层,目标是确保表…

vray学习笔记(3)-多维子材质是个什么东西

多维子材质是个什么东西&#xff1f;为什么出现这个概念&#xff1f; 在3dsmax官方网站&#xff0c;我们可以看到它的定义&#xff1a; The Multi/Sub-Object material lets you assign different materials at the sub-object level of your geometry. 意思是多维子材质这个概…

Hello JavaFX 2.0:命令行介绍

我从博客文章Hello JavaFX 2.0&#xff1a;NetBeans 7.1 beta的介绍中&#xff0c;从NetBeans 7.1 beta的角度看了一个无处不在的Hello World示例的简单JavaFX版本。 在本文中&#xff0c;我将介绍仅使用命令行工具通过JavaFX实现的Hello World版本。 JavaFX 2.0 API文档包括ja…

matlab空格会消失了,如何在Matlab中自动删除保存的尾随空格?

我有同样的需求,并写了一个小脚本来做一些接近的事情.将以下内容放在MATLAB desktop shortcut中.每当您单击快捷方式按钮时,它将从编辑器中的活动文件中删除尾随空格.不如在保存时自动执行它 – 你需要记住在保存之前按下按钮 – 但差不多.测试在11b,12a和13b,但在12b也应该没问…

object to 字符串json

1 package com.beijxing.TestMain;2 3 import com.beijxing.entity.Student;4 import com.google.gson.Gson;5 import com.google.gson.annotations.SerializedName;6 7 /** 8 * 9 * author 作者 : ywp 10 * version 创建时间&#xff1a;2016年10月30日 下午9:21:33 11 */ 12…

JS 对象(Object)和字符串(String)互转

var jsObj {}; jsObj.testArray [1,2,3,4,5]; jsObj.name CSS3; jsObj.date 8 May, 2011; var str JSON.stringify(jsObj); var str1 JSON.parse(str); var str2 JSON.stringify(str1);alert(str);alert(str1); alert(str2);对象拷贝&#xff1a;var newObj JSON…

php 后退按钮事件,php – 后退按钮的会话问题

我在php文件中有这个代码,它包含在我要共享的所有页面中并保护我的页面.session_name("login");session_start();if (!isset($_SESSION[UserId])) {if(!header("Location: https://subdomain.mywebsite.com/")){ die("Unauthorized access"); }}…