簡體   English   中英

使用共享模塊中的 spring-beans.xml 文件(在“資源”文件夾中)和 gradle 多模塊(子項目)

[英]Using a spring-beans .xml file (in 'resources' folder) from a shared module with gradle multi module (subproject)

(為了幫助解決這個問題,我在這個問題的底部有 github 個鏈接)

我有(並且“從”以下 gradle 多個模塊/項目開始)

設置.gradle

rootProject.name = 'com.mycompany.myteam.myapp-rootProjectName'

include ':source:java:myapproot:myapp-toplayer-console-di-xml-one'
include ':source:java:myapproot:myapp-business-logic'
(maybe even a few that are purely .java/.class "code logic" libraries)

在子項目中:

':來源:java:myapproot:myapp-toplayer-console-di-xml-one'

我有典型的 Spring-Boot 啟動和使用 applicationContext.xml 的 spring-bean 設置。

./source/java/myapproot/myapp-toplayer-console-di-xml-one/src/main/java/demo/SpringBootApplicationContextXmlConsoleApplication.java
--
./source/java/myapproot/myapp-toplayer-console-di-xml-one/src/main/resources/applicationContext.xml
./source/java/myapproot/myapp-toplayer-console-di-xml-one/src/main/resources/orch.one.di.xml
./source/java/myapproot/myapp-toplayer-console-di-xml-one/src/main/resources/clientporxy.one.di.xml

“applicationContext.xml”的內容如下。 請注意,它有一個指向其他一些 .xml 文件的“指針”“導入”條目。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">


    <import resource="orch.one.di.xml"/>

    <import resource="clientproxy.one.di.xml"/>

</beans>

上面的一切都很好。 多年來,我一直在為許多不同的項目采用上述方法。

================================================ ==========

我想要做的是將 2 個“額外”*.di.xml 文件放入另一個gradle 模塊中。

設置.gradle

rootProject.name = 'com.mycompany.myteam.myapp-rootProjectName'

include ':source:java:myapproot:myapp-toplayer-console-di-xml-one'
include ':source:java:myapproot:myapp-business-logic'

    (new one below)
include ':source:java:myapproot:myapp-shared-resxex'

我想將 *.di.xml 文件移動到這個不同的/新的 gradle-subproject/module。 (':source:java:myapproot:myapp-shared-resxex'要清楚)

所以現在我已經移動了兩個 *.di.xml 文件。

文件位置在這里:(在“資源”下)

./source/java/myapproot/myapp-shared-resxex/src/main/resources/orch.one.di.xml
./source/java/myapproot/myapp-shared-resxex/src/main/resources/clientproxy.one.di.xml

所以現在當我啟動“主”應用程序時,出現如下錯誤(我有點預料到這些錯誤)

Caused by: java.io.FileNotFoundException: 

    ./source/java/myapproot/myapp-toplayer-console-di-xml-one/build/resources/main/clientproxy.one.di.xml

    (No such file or directory)
    at java.base/java.io.FileInputStream.open0(Native Method)
    at java.base/java.io.FileInputStream.open(FileInputStream.java:219)
    at java.base/java.io.FileInputStream.<init>(FileInputStream.java:157)
    at java.base/java.io.FileInputStream.<init>(FileInputStream.java:112)
    at java.base/sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:86)
    at java.base/sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:184)
    at org.springframework.core.io.UrlResource.getInputStream(UrlResource.java:187)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:333)

我已經“嘗試”(並完成)了這樣的事情:

https://docs.gradle.org/current/userguide/cross_project_publications.html

Gradle:多個java項目的公共資源依賴

模塊如何使用 gradle 多模塊使用另一個模塊的資源

https://discuss.gradle.org/t/how-to-bundle-static-resources-from-other-subproject-into-java-application/42076

就像很多天和很多小時都在試圖找出神奇的醬汁一樣。

所以,我的“一般”問題是

如何讓 spring bean.xml 文件從不同的 gradle-subproject/module 工作?

我將展示我的最新嘗試:

./source/java/myapproot/myapp-shared-resxex/build.gradle

configurations {
    myCoolConfigurationName
}

task tryToPackageStuffForOtherSubprojectsTask(type: Jar) {
    archiveClassifier
    from sourceSets.main.resources
}

artifacts {
    myCoolConfigurationName tryToPackageStuffForOtherSubprojectsTask
}

dependencies {

    implementation project(':source:java:myapproot:clientproxies:myclientproxy-root:myclientproxy-domain')
    implementation project(':source:java:myapproot:clientproxies:myclientproxy-root:myclientproxy-interfaces')
    implementation project(':source:java:myapproot:clientproxies:myclientproxy-root:myclientproxy-concrete')


}

進而:

./source/java/myapproot/myapp-toplayer-console-di-xml-one/build.gradle

plugins {
    id "application"
}

apply plugin : "java"

ext {
    javaMainClass = "demo.SpringBootApplicationContextXmlConsoleApplication"
}

application {
    mainClassName = javaMainClass
}


task myCustomPrintClasspathTask  {
    doLast {
        configurations.runtimeClasspath.each { println 'helloThere->' + it }
    }
}


dependencies {

    //the below line, if left not-commented-out, will produce a warning : "Execution optimizations have been disabled for task"
    implementation project(path: ':source:java:myapproot:myapp-shared-resxex', configuration: 'myCoolConfigurationName')


    implementation(group: 'org.springframework.boot', name: 'spring-boot-starter', version: springBootVersion) {
        exclude module: "logback-classic"
    }

    implementation(group: 'org.springframework.boot', name: 'spring-boot-autoconfigure', version: springBootVersion) {
        exclude module: "logback-classic"
    }

    implementation project(":source:java:myapproot:myapp-shared-resxex")
    implementation project(':source:java:myapproot:myapp-business-logic')

    implementation project(':source:java:myapproot:clientproxies:myclientproxy-root:myclientproxy-domain')
    implementation project(':source:java:myapproot:clientproxies:myclientproxy-root:myclientproxy-interfaces')
    implementation project(':source:java:myapproot:clientproxies:myclientproxy-root:myclientproxy-concrete')


    implementation group: 'org.apache.commons', name: 'commons-lang3', version: commonsLangVersion
    implementation group: 'javax.inject', name: 'javax.inject', version: "${javaxInjectVersion}"

    implementation group: 'org.slf4j', name: 'slf4j-api', version: slf4jVersion
    implementation group: 'org.slf4j', name: 'slf4j-simple', version: slf4jSimpleVersion

    testImplementation group: 'junit', name: 'junit', version: junitVersion
    testImplementation group: 'org.mockito', name: 'mockito-core', version: mockitoVersion

}

當我運行(一個干凈的構建然后)自定義任務時:

$ ./gradlew clean build
$ ./gradlew myCustomPrintClasspathTask

我得到以下 output:

> Task :source:java:myapproot:myapp-toplayer-console-di-xml-one:myCustomPrintClasspathTask

helloThere->./source/java/myapproot/myapp-shared-resxex/build/libs/myapp-shared-resxex.jar

helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter/2.7.5/c28e1546461803490588085345ba5d2897d232bc/spring-boot-starter-2.7.5.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-autoconfigure/2.7.5/96646e63a2296d0a3209383e81cdb8c87ab2f913/spring-boot-autoconfigure-2.7.5.jar
helloThere->./source/java/myapproot/myapp-business-logic/build/libs/myapp-business-logic.jar
helloThere->./source/java/myapproot/clientproxies/myclientproxy-root/myclientproxy-concrete/build/libs/myclientproxy-concrete.jar
helloThere->./source/java/myapproot/clientproxies/myclientproxy-root/myclientproxy-interfaces/build/libs/myclientproxy-interfaces.jar
helloThere->./source/java/myapproot/clientproxies/myclientproxy-root/myclientproxy-domain/build/libs/myclientproxy-domain.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-lang3/3.12.0/c6842c86792ff03b9f1d1fe2aab8dc23aa6c6f0e/commons-lang3-3.12.0.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/javax.inject/javax.inject/1/6975da39a7040257bd51d21a231b76c915872d38/javax.inject-1.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-simple/1.7.36/a41f9cfe6faafb2eb83a1c7dd2d0dfd844e2a936/slf4j-simple-1.7.36.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-logging/2.7.5/61f4c53e35baa31a269bbeb7bb9d5e781448feef/spring-boot-starter-logging-2.7.5.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-to-slf4j/2.17.2/17dd0fae2747d9a28c67bc9534108823d2376b46/log4j-to-slf4j-2.17.2.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.slf4j/jul-to-slf4j/1.7.36/ed46d81cef9c412a88caef405b58f93a678ff2ca/jul-to-slf4j-1.7.36.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-api/1.7.36/6c62681a2f655b49963a5983b8b0950a6120ae14/slf4j-api-1.7.36.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot/2.7.5/fd04e228e6e21b7ad13c10ae29afd31868d842e5/spring-boot-2.7.5.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/jakarta.annotation/jakarta.annotation-api/1.3.5/59eb84ee0d616332ff44aba065f3888cf002cd2d/jakarta.annotation-api-1.3.5.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.springframework/spring-context/5.3.23/530b36b2ce2c9e471c6a260c3f181bcd20325a58/spring-context-5.3.23.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.springframework/spring-aop/5.3.23/30d0034ba29178e98781d85f51a7eb709a628e9b/spring-aop-5.3.23.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.springframework/spring-beans/5.3.23/3bdefbf6042ed742cbe16f27d2d14cca9096a606/spring-beans-5.3.23.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.springframework/spring-expression/5.3.23/3a676bf4b9bc42bd37ab5ad264acb6ceb63397a2/spring-expression-5.3.23.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.springframework/spring-core/5.3.23/91407dc1106ea423c44150f3da1a0b4f8e25e5ca/spring-core-5.3.23.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.yaml/snakeyaml/1.30/8fde7fe2586328ac3c68db92045e1c8759125000/snakeyaml-1.30.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.springframework/spring-jcl/5.3.23/3c7eb5fcca67b611065f73ff4325e398f8b051a3/spring-jcl-5.3.23.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-api/2.17.2/f42d6afa111b4dec5d2aea0fe2197240749a4ea6/log4j-api-2.17.2.jar

如果我“窺視”jar:

./source/java/myapproot/myapp-shared-resxex/build/libs/myapp-shared-resxex.jar

我確實看到了兩個 *.di.xml 文件。

然后如果我運行:

$ ./gradlew run

我繼續得到:

Caused by: java.io.FileNotFoundException: ./source/java/myapproot/myapp-toplayer-console-di-xml-one/build/resources/main/clientproxy.one.di.xml (No such file or directory)
        at java.base/java.io.FileInputStream.open0(Native Method)
        at java.base/java.io.FileInputStream.open(FileInputStream.java:219)
        at java.base/java.io.FileInputStream.<init>(FileInputStream.java:157)
        at java.base/java.io.FileInputStream.<init>(FileInputStream.java:112)
        at java.base/sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:86)
        at java.base/sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:184)
        at org.springframework.core.io.UrlResource.getInputStream(UrlResource.java:187)
        at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:333)
        ... 32 more

我的./gradle/wrapper/gradle-wrapper.properties 文件(為了完整性和了解我的 gradle-version)

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

.....

帶有代碼的 Github 回購。

https://github.com/granadacoder/gradle-multi-with-spring-bean-proof

“主要”分支...有一個工作的 spring-bean di.xml 設置。 “主要”分支與我上面的評論“上面的一切都很好”有關。

我有第二個分支(和一個 PR,所以你可以看到“差異”)。

分支:

https://github.com/granadacoder/gradle-multi-with-spring-bean-proof/tree/feature/move-spring-bean-xml-files-try-1

和 PR(從功能分支到主分支以顯示“差異”)

https://github.com/granadacoder/gradle-multi-with-spring-bean-proof/pull/2/files

好的。

我找到了一個“舊”文檔頁面。

https://docs.spring.io/spring-framework/docs/3.0.0.M4/reference/html/ch04s07.html

我會張貼上面 URL 的引述,以防它“消失”.. 特別是因為它是“舊”文檔。

//開始文章引用

4.7.2.2 classpath*: 前綴在構建基於 XML 的應用程序上下文時,位置字符串可以使用特殊的 classpath*: 前綴:

ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml"); 這個特殊前綴指定必須獲取所有與給定名稱匹配的類路徑資源(在內部,這實際上是通過 ClassLoader.getResources(...) 調用發生的),然后合並以形成最終的應用程序上下文定義。

[注意] 類路徑*:可移植性 通配符類路徑依賴於底層類加載器的 getResources() 方法。 由於現在大多數應用程序服務器都提供自己的類加載器實現,因此行為可能會有所不同,尤其是在處理 jar 文件時。 檢查類路徑* 是否有效的一個簡單測試是使用類加載器從類路徑上的 jar 中加載文件:getClass().getClassLoader().getResources("")。 使用具有相同名稱但位於兩個不同位置的文件嘗試此測試。 如果返回不適當的結果,請檢查應用程序服務器文檔以了解可能影響類加載器行為的設置。

“classpath*:”前綴也可以與位置路徑的 rest 中的 PathMatcher 模式組合,例如“classpath*:META-INF/*-beans.xml”。 在這種情況下,解析策略相當簡單:在最后一個非通配符路徑段上使用 ClassLoader.getResources() 調用來獲取 class 加載器層次結構中的所有匹配資源,然后關閉每個資源相同的 PathMatcher 解析策略上面描述的用於通配符子路徑。

//結束文章引用

所以我忘記了使用類路徑(在文件名等之前)的“字符串魔法”。

我能夠將我的 applicationContext.xml 文件更新為以下內容。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">


    <!-- below are "imports" to OTHER (spring-bean) di.xml files -->

    <import resource="classpath:clientproxy.one.di.xml"/>

    <import resource="classpath*:orchestrators.one.di.xml"/>



</beans>

您可以在下面的 SOF 問題/答案中了解使用“*”(在類路徑之后)之間的區別。

Spring 類路徑前綴差異

為清楚起見......我所做的只是將兩個 di.xml 文件“移動”到“其他”gradle/module-subproject。 我沒有使用我在原始問題中顯示的任何“myCoolConfigurationName”內容......作為我的“嘗試”之一。

“如此簡單”…………我為自己為此奮斗的日子感到高興和難以置信……

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM