Loading External JARs into Spring Boot: Four Practical Approaches
This article explains how to make custom classes visible to Spring Boot by loading external JAR files through four methods—extending the classpath, using Spring Boot's loader.path parameter, creating a custom ClassLoader, and modifying the boot classpath—while also showing how to configure scanning and packaging details.
To make a custom class available to Spring Boot you only need to complete two steps: load the class into the JVM and let Spring scan the class.
Based on the previous article about ClassLoader and Spring Boot startup, three straightforward solutions are proposed.
Expand the -cp option so that the AppClassLoader loads external JARs.
Use Spring Boot's startup parameter loader.path to specify additional JAR locations.
Implement a custom classloader to load JARs from a fixed directory.
Assume the JARs to be loaded are placed under /user/local/java/plugins . The following sections describe each solution in detail.
Solution 1: Expand -cp with AppClassLoader
Specify the classpath with the classpath argument. The table shows when the classpath takes effect:
Command
Classpath Effective
Explanation
java -cp .;lib/x.jar Test
✔
Runs a class
java -cp lib/x.jar -jar app.jar
✖
Runs a JAR
When the -cp option works, Spring Boot’s Main-Class is JarLauncher , so the launch command becomes:
java -cp /user/local/java/plugins org.springframework.boot.loader.JarLauncherAdvantage: simple implementation.
Disadvantage: every JAR uses the same launch command, making differentiation difficult.
Solution 2: Use Spring Boot’s loader.path with java -jar
Since most Spring Boot applications are packaged as JARs and started with java -jar boot.jar , the -cp option is ineffective. By adding the loader.path parameter you can load additional JARs, but it only works under certain conditions (see the accompanying diagram).
To make loader.path effective, configure the Main-Class to PropertiesLauncher in build.gradle :
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>false</includeSystemScope>
<!-- Use ZIP layout so -Dloader.path works -->
<layout>ZIP</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<finalName>Test</finalName>
</build>The layout can be set to:
JAR – standard executable JAR ( Main-Class: org.springframework.boot.loader.JarLauncher )
WAR – executable WAR (requires servlet container in WEB-INF/lib-provided )
ZIP – similar to JAR, uses PropertiesLauncher
MODULE – packages all dependencies except those with provided scope, without any Spring Boot launcher
NONE – packages all dependencies but no launcher
Both JarLauncher and PropertiesLauncher load JARs via org.springframework.boot.loader.LaunchedURLClassLoader , meaning they share the same class‑loading mechanism.
Note: PropertiesLauncher starts noticeably slower (≈20 s) than JarLauncher (≈8 s) for the same program.
Solution 3: Custom ClassLoader
Implement a custom ClassLoader that loads JARs from a fixed directory or an environment‑specified path. This approach offers high flexibility but requires a suitable hook in the application startup.
// Example of invoking a custom class loader
SpringApplication.run(SpringBootDemo.class, args);Solution 4: Modify -Xbootclasspath/a or java.ext.dirs
Changing the system ClassLoader’s behavior is unsafe and not recommended.
Scanning Loaded Classes into the Spring Container
If the business JAR’s packages start with com.demo , you can pre‑define the scan base packages in the main application:
@SpringBootApplication(scanBasePackages = {"com.demo"})
public class SpringBootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class, args);
}
}When the package prefix does not match, add the required auto‑configuration classes to META-INF/spring.factories , e.g., for MyBatis‑Plus:
# Auto Configure
org.springframework.boot.env.EnvironmentPostProcessor=\
com.baomidou.mybatisplus.autoconfigure.SafetyEncryptProcessor
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.baomidou.mybatisplus.autoconfigure.IdentifierGeneratorAutoConfiguration,\
com.baomidou.mybatisplus.autoconfigure.MybatisPlusLanguageDriverAutoConfiguration,\
com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfigurationThe article concludes with a reminder that the content is intended for backend developers and includes a community invitation (advertisement) that is not part of the technical guide.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.