首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring Roo 進階附加組件與包裝器附加組件開發實戰

     編輯:Java 相關知識

承接《Spring Roo 簡介,第 3 部分:開發 Spring Roo 附加組件》,本文深入講解進階附加組件與包裝器附加組件的開發。建議先閱讀第 3 部分理解附加組件架構與簡單附加組件創建。

進階附加組件:代碼生成的核心力量

簡單附加組件僅能修改 POM、配置檔;進階附加組件額外賦予生成 Java 原始碼與 ITD (Inter-type Declarations, *.aj) 的能力,是 Spring Roo 代碼生成的核心。

現有進階附加組件剖析:JPA 為例

Roo Shell 執行:

project --topLevelPackage com.dw.demo --projectName entity-demo
jpa setup --database FIREBIRD --provider HIBERNATE
entity --class ~.domain.Book

jpa setup 輸出(配置職責,屬簡單附加組件範疇):

Created SRC_MAIN_RESOURCES/META-INF/spring/database.properties
Updated ROOT/pom.xml [added dependencies ...]
Updated SRC_MAIN_RESOURCES/META-INF/spring/applicationContext.xml
Created SRC_MAIN_RESOURCES/META-INF/persistence.xml

entity 輸出(生成 Java 與 *.aj,標誌進階附加組件):

Created SRC_MAIN_JAVA/com/dw/demo/domain
Created SRC_MAIN_JAVA/com/dw/demo/domain/Book.java
Created SRC_MAIN_JAVA/com/dw/demo/domain/Book_Roo_Configurable.aj
Created SRC_MAIN_JAVA/com/dw/demo/domain/Book_Roo_Jpa_Entity.aj
Created SRC_MAIN_JAVA/com/dw/demo/domain/Book_Roo_Entity.aj
Created SRC_MAIN_JAVA/com/dw/demo/domain/Book_Roo_ToString.aj

Book.java 僅含註解:

@RooJavaBean @RooToString @RooEntity
public class Book { }

註解驅動 ITD 生成:@RooToString → Book_Roo_ToString.aj (toString()),@RooEntity → 實體相關 ITD。ITD 允許在獨立編譯單元修改類型靜態結構(增欄位/方法/介面),Roo 管理其全生命週期。

運行機制

  • Shell 啟動掃描實作 CommandMarker 的類,註冊命令。
  • 進階附加組件向 OSGi 運行時註冊服務,指定觸發條件(通常為註解)。
  • 用戶執行命令建立帶註解的 Java 類 → 相應附加組件被觸發生成 ITD。

實戰:開發 compareTo 進階附加組件

目標:為實體自動實作 Comparable 介面與 compareTo() 方法(使用 Apache Commons Lang CompareToBuilder)。

專案創建

addon create advanced --topLevelPackage org.xebia.roo.addon.compareto --projectName spring-dw-roo-compareto-addon

生成核心構件

  • ComparetoCommands.java:實作 CommandMarker,@CliAvailabilityIndicator 控制命令可見性,@CliCommand 註冊命令 (value/help)。
  • ComparetoOperations.java / ComparetoOperationsImpl.java:命令委托實作。核心方法:
      isCommandAvailable():上下文感知(如專案已建立)。
      setup():配置任務(加依賴、倉庫、Spring 上下文)。
      annotateType():給指定類型加註解 (@RooCompareto)。
      annotateAll():掃描所有 @RooJavaBean 類型批量加註解。
  • RooCompareto.java:觸發代碼生成的註解。
  • ComparetoMetadataProvider.java:OSGi 服務,註冊元數據增減觸發器,getMetadata() 供 Roo 呼叫。
  • ComparetoMetadata.java:核心代碼生成類,使用 ItdTypeDetailsBuilder 構建 ITD(增欄位/方法/介面/註解)。

需求實現三步驟

  1. 目標專案加入 commons-lang3:3.1 Maven 依賴。
  2. 實體類實作 java.lang.Comparable 介面。
  3. 生成 compareTo() 方法 ITD。

修改 configuration.xml 管理依賴

<configuration>
  <dependencies>
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.1</version>
    </dependency>
  </dependencies>
</configuration>

修改 ComparetoOperationsImpl.setup() 讀取新依賴

public void setup() {
    projectOperations.addRepository("", new Repository(...));
    List<Dependency> dependencies = new ArrayList<>();
    dependencies.add(new Dependency("org.xebia.roo.addon.compareto", ..., DependencyType.JAR, DependencyScope.PROVIDED));
    Element configuration = XmlUtils.getConfiguration(getClass());
    for (Element depEl : XmlUtils.findElements("/configuration/dependencies/dependency", configuration)) {
        dependencies.add(new Dependency(depEl));
    }
    projectOperations.addDependencies("", dependencies);
}

實作 Comparable 介面(ComparetoMetadata 建構子)

JavaType comparableInterface = new JavaType("java.lang.Comparable");
builder.addImplementsType(comparableInterface);

構建 compareTo() 方法

使用 MethodMetadataBuilder,分步驟:

  1. 參數 Object obj,回傳 int。
  2. instanceof 檢查失敗回傳 -1。
  3. 強制轉型:Book rhs = (Book) obj;。
  4. 使用 CompareToBuilder 串聯所有欄位 .append(this.field, rhs.field) 並 .toComparison()。

關鍵挑戰:ComparetoMetadata 需獲取目標類所有欄位。解法:ComparetoMetadataProvider.locateFields() 過濾靜態/暫態/集合/陣列/版本欄位,回傳 FieldMetadata 列表傳給 ComparetoMetadata。

最終 getCompareToMethod() 動態構建方法體:

final ImportRegistrationResolver imports = builder.getImportRegistrationResolver();
imports.addImport(new JavaType("org.apache.commons.lang3.builder.CompareToBuilder"));
// ... 構建 instanceof、轉型、CompareToBuilder 鏈式調用 ...
bodyBuilder.appendFormalLine(builder.toString());

測試驗證

  1. mvn clean install 建構附加組件 Jar (需 GPG 密碼)。
  2. 建立測試專案 bookshop,執行 JPA 設置與實體/欄位建立命令。
  3. osgi start --url file://<jar路徑> 安裝啟動附加組件。
  4. compareto + Tab 顯示三命令:setup、add、all。
  5. compareto setup → 更新 POM (加倉庫、commons-lang3、附加組件註解 Jar)。
  6. compareto all → 生成 Book_Roo_Compareto.aj:
privileged aspect Book_Roo_Compareto {
    declare parents: Book implements java.lang.Comparable;
    public int Book.compareTo(java.lang.Object obj) {
        if (!(obj instanceof Book)) return -1;
        Book rhs = (Book) obj;
        return new CompareToBuilder()
            .append(author, rhs.author)
            .append(id, rhs.id)
            .append(price, rhs.price)
            .append(title, rhs.title)
            .toComparison();
    }
}

坑點修正:perform package 失敗因 Maven 無法解析附加組件依賴。解法:建立獨立註解模組 xebia-spring-roo-addon-annotations,configuration.xml 引入該 Jar 而非附加組件 Jar,並更新 setup() 解析 /configuration/repositories。

包裝器附加組件:非 OSGi JDBC 驅動 OSGi 化

場景:對 Oracle 資料庫反向工程需 OSGi 版 JDBC 驅動,版權限制 Spring Roo 不提供。包裝器附加組件將非 OSGi Jar 轉為 OSGi Bundle。

Oracle JDBC 包裝實戰

  1. 安裝本地 Maven:
    mvn install:install-file -Dfile=ojdbc5.jar -DgroupId=com.oracle -DartifactId=ojdbc5 -Dversion=11.2.0.2 -Dpackaging=jar
  2. 建立目錄 oracle-wrapper-addon,進入 Roo Shell:
    addon create wrapper --topLevelPackage com.oracle.wrapper.jdbc --groupId com.oracle --artifactId ojdbc5 --version 11.2.0.2 --vendorName Oracle --licenseUrl oracle.com
    僅生成 pom.xml。
  3. perform command --mavenCommand bundle:bundle 生成 OSGi Bundle。

完成!可用於反向工程等需 OSGi 驅動場景。

結語

本文完整演示進階附加組件(代碼生成核心)與包裝器附加組件(第三方 Jar OSGi 化)開發全流程。擴展 Spring Roo 功能,優先考慮附加組件機制。下一篇將探討使用 Spring Roo 開發 GWT 應用。

描述名字大小下載方法
範例代碼bookshop.zip14KBHTTP
範例代碼spring-dw-roo-compareto-addon.zip18KBHTTP
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved