如何复用Spring Boot JarLauncher自定义子类?Gradle配置咨询
Let's tackle your problem head-on—this is a common scenario when dealing with conflicting nested dependencies in Spring Boot, and reusing a custom launcher across projects is smart practice.
Can I directly reference the custom launcher from a dependency Jar in the Boot-Jar root?
Short answer: No. Here's why:
Spring Boot's JarLauncher (and its subclasses) need to be loaded by the system classloader when the JVM starts. The system classloader only looks for classes in the root of your Spring Boot executable Jar (the same level as org/springframework/boot/loader/).
If your custom launcher is packaged inside a dependency Jar under BOOT-INF/lib/, the system classloader won't be able to find it—those Jars are only loaded by Spring Boot's internal LaunchedURLClassLoader after the initial launcher starts. So you can't set your Main-Class to a class inside BOOT-INF/lib/; you need to extract the custom launcher class to the root of your executable Jar.
Gradle Configuration Steps
Step 1: Package Your Custom Launcher as a Reusable Dependency
First, create a standalone Java project for your CustomJarLauncher, then publish it to your Maven repository. Here's the Gradle config for this project:
plugins { id 'java' id 'maven-publish' } repositories { mavenCentral() } dependencies { // Match the Spring Boot version used in your business projects implementation 'org.springframework.boot:spring-boot-loader:2.7.15' } publishing { publications { mavenJava(MavenPublication) { from components.java } } repositories { maven { url = uri("https://your-maven-repo-url") // e.g., Nexus, Artifactory, or local repo credentials { username = System.getenv('MAVEN_USER') password = System.getenv('MAVEN_PASS') } } } }
Step 2: Configure Business Projects to Use the Custom Launcher
In each Spring Boot project that needs the custom launcher, add the dependency and configure the bootJar task to extract the launcher class to the Jar root, then set it as the Main-Class.
plugins { id 'org.springframework.boot' version '2.7.15' id 'java' } repositories { mavenCentral() maven { url = uri("https://your-maven-repo-url") } } dependencies { // Add your custom launcher dependency, exclude duplicate spring-boot-loader implementation('com.yourcompany:custom-boot-launcher:1.0.0') { exclude group: 'org.springframework.boot', module: 'spring-boot-loader' } // Your other business dependencies... } bootJar { // Extract the custom launcher class to the root of the executable Jar into('') { from { // Find the custom launcher dependency Jar and extract the class file configurations.runtimeClasspath.find { it.name.startsWith('custom-boot-launcher') } .collect { zipTree(it).matching { include 'com/yourcompany/CustomJarLauncher.class' } } } } // Set the custom launcher as the Main-Class in the manifest manifest { attributes 'Main-Class': 'com.yourcompany.CustomJarLauncher' } }
Key Notes
- Version Alignment: Ensure the
spring-boot-loaderversion in your custom launcher project matches the Spring Boot version in your business projects to avoid compatibility issues. - Cleanup: After extracting the launcher class, you can optionally exclude the entire
custom-boot-launcherJar fromBOOT-INF/lib/since the class is already in the root:bootJar { // ... existing config ... excludes += 'BOOT-INF/lib/custom-boot-launcher-*.jar' } - Verification: After building, unzip your executable Jar—you should see
com/yourcompany/CustomJarLauncher.classat the root (same level asorg/springframework/boot/loader/), and the manifest should list it as theMain-Class.
内容的提问来源于stack exchange,提问作者tony_k

