自制代碼生成器中的一些問題與思考

1. 引言

去年7月開始參加工做,剛開始被前後分配了兩個製做基礎頁面的任務,也就是常規的增刪改查,包括前端頁面的 vue 文件以及後端實體類和各邏輯層的接口與實現類,總共須要建立 9 個文件,1個 vue、7個 java,1個 xml。前端

雖然可使用 MybatisGenerator 根據數據庫表自動生成實體類和 Mapper 層文件,但再往上的邏輯層就須要手動編寫。Ctrl+C,Ctrl+V,再根據具體的實體類名稱去修改,前先後後花了1個小時把一個基礎頁面調通。以爲實在太麻煩了,因此產生了寫個代碼生成器的念頭,一鍵生成9個文件,從而告別複製粘貼。效果以下所示:vue

代碼生成器演示圖

2. 技術點

  1. 根據代碼模板生成,使用了經常使用的 FreeMarker 做爲模板引擎。
  2. 爲了簡化使用操做,作了個 GUI 把已有的 MybatisGenerator 和新編寫的生成代碼邏輯封裝起來。使用了 JavaFX,能夠拖控件,挺省事的。
  3. 爲了保存生成文件的位置信息、鏈接數據庫信息,以及在不一樣項目中切換,使用了 SQLite,方便。

3. 問題

如下記錄所遇到的一些問題:java

  1. 在 MybatisGenerator 生成實體類( java 文件)後,須要將實體類編譯成 class 文件,再加載進 JVM 中,才能經過反射讀取到實體類屬性。實現步驟以下:數據庫

    • 讀取 java 文件內容
    • JavaCompiler 動態編譯生成class文件
    • 經過反射利用 ClassLoader 的 addUR L方法,將 class 文件的路徑加入到 classpath 中(這裏須要加入 classpath 的主要緣由是最後的程序被打包成了 jar 包,而運行時生成的 class 文件是不會在 jar 包中,那麼其路徑也不在 classpath 中)
    • 加載類(Class.forName)
  2. 在用 IDE 開發時,能夠經過 File 類成功找到資源文件:編程

    File configFile = new File("generatorConfig.xml");

    可是打包成 jar 包後,就連資源文件一塊兒打包了,而這時是沒法經過 file:/e:/codeGenerator.jar/generatorConfig.xml 這種形式的文件 URL 找到文件的。後端

    這是由於 jar 包是個單獨文件,而不是文件夾,而須要經過 ClassLoader 提供的 getResourceAsStream 方法獲取 jar 包中的內容。緩存

    InputStream configFile = Thread.currentThread().getContextClassLoader().getResourceAsStream("generatorConfig.xml");

4. 思考

《阿里巴巴Java開發手冊》中關於應用分層推薦使用4層,分別是 Web 層、Service 層、Manager 層和 DAO 層。而咱們在開發的過程當中常常能看到每一層都須要面向接口編程,例如 xxxManager。這麼作是爲了達到「對修改封閉,對擴展開放」的原則。app

但實際狀況是一個接口一般只有一個實現類,例如 xxxManagerImpl ,大多數的代碼一般都並不會有擴展的狀況。這樣會致使的問題就有像前文所說一個簡單基礎數據的增刪改查就須要 7 個 java 類,代碼量增長了。不免有些是在爲了使用接口而使用接口的味道。spa

那麼是否須要面向接口編程?代理

下面讓咱們試想一下,在一個接口只有一個實現類的狀況下,不使用面向接口編程的好處和壞處。

好處,很顯然,咱們只須要編寫、維護一份代碼(實現類),代碼量減小了。

壞處,則是不可控的類信息暴露控制。例如,想經過 AOP 實現方法級別的緩存,而且使用註解標記方法,若是咱們失誤將註解標記在了 private 方法上,而因爲基於 CGLIB 的 AOP 是經過生成子類來建立代理,因此該 AOP 將不會生效;但若是是基於接口動態代理,則不會由於失誤出現這個問題。

最後,嘗試給這個問題一個暫時的答案:

在大型團隊進行面向企業應用開發中,爲了不意外的風險,儘可能使用接口編程。

而當團隊規模不大,瞭解不使用接口的風險,可以承受該風險,業務邏輯變動頻繁時,不是面向企業應用開發,可考慮不使用接口,直接經過實現類開發。

相關文章
相關標籤/搜索