使用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.pswp.cn/news/372151.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/372151.shtml
英文地址,請注明出處:http://en.pswp.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"); }}…