We want to make a plugin-type main program based on spring. The main program can load other Spring jars and non-spring jars as a plugin. Each plugin is based on IPlugin, And the plugin's 'IPlugin' class same as the main program's 'IPlugin' class. We make the non-spring plugin work by 'URLClassLoader', But the way not for the spring plugin. In the 'TestPlugin' project, the implementation named of 'PluginTest' and execute 'SpringApplication.run(PluginTest.class, args);' in function 'init(String[])'. 'ClassNotFoundException' occurred for load class 'PluginTest'(cause of spring jars structure).
String pluginClassName = "com.example.demo.PluginTest";
c = newClassLoader.loadClass(pluginClassName);
So, We replace the pom 'plugins' section like following:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>${project.artifactId}-${project.version}</finalName>
<appendAssemblyId>false</appendAssemblyId>
<attach>false</attach>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
But, We got another error 'Caused by: java.lang.NoClassDefFoundError: com/zaxxer/hikari/HikariConfig' (JDBC used in test project). I don't know how to properly load other spring jars at run time.
Whole codes of plugin loader:
@Component
public class Initializer implements ApplicationRunner
{
@Override
public void run(ApplicationArguments args)
{
String jarPath = "e:/tmp/demo-0.0.1-SNAPSHOT.jar";
File file = new File(jarPath);
IPlugin p;
try
{
ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
URLClassLoader newClassLoader = new URLClassLoader(new URL[]{file.toURI().toURL()}, oldClassLoader);
Thread.currentThread().setContextClassLoader(newClassLoader);
String pluginClassName = "com.example.demo.PluginTest";
Class<?> c = newClassLoader.loadClass(pluginClassName);
Object pluginTest = c.newInstance();
p = (IPlugin)pluginTest;
p.init(new String[]{
"--spring.config.location=e:/tmp/application.properties"
});
}
catch (Exception e)
{
System.out.println(e);
e.printStackTrace();
}
}
}
Thanks!