Hi all. I'm trying to make a program that can load an unknown set of plugins from a sub-folder, "Plugins". All of these plugins implement the same interface. What I need to know is how do I find all of the classes in this folder so that I can instantiate and use them?
Look through the folder with File.listFiles() and use a JarClassLoader instance to load the classes in there.
Or, add a description.xml in each of those jars if they are on the classpath, and use getClass().getClassLoader().findResources("description.xml") to load all descriptions, and then you have all the plugin classes to load.
Check java.util.ServiceLoader
A service is a well-known set of interfaces and (usually abstract) classes. A service provider is a specific implementation of a service. The classes in a provider typically implement the interfaces and subclass the classes defined in the service itself. Service providers can be installed in an implementation of the Java platform in the form of extensions, that is, jar files placed into any of the usual extension directories. Providers can also be made available by adding them to the application's class path or by some other platform-specific means.
This article explains the details.
MyInterface.java
A stub interface.
package test;
public interface MyInterface {
public void printSomething();
}
TestClass.java
A test class to be loaded, implementing your interface.
import test.MyInterface;
public class TestClass implements MyInterface {
public void printSomething() {
System.out.println("Hello World, from TestClass");
}
}
(Compiled class file placed in "subfolder/".)
Test.java
A complete test program that loads all class files from "subfolder/" and instantiates and runs the interface method on it.
package test;
import java.io.File;
public class Test {
public static void main(String[] args) {
try {
ClassLoader cl = ClassLoader.getSystemClassLoader();
File subfolder = new File("subfolder");
for (File f : subfolder.listFiles()) {
String s = f.getName();
System.out.println("Loading " + s);
Class cls = cl.loadClass(s.substring(0, s.lastIndexOf('.')));
MyInterface o = (MyInterface) cls.newInstance();
o.printSomething();
}
} catch (ClassNotFoundException e) {
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
}
}
}
Output from Test program above:
Loading TestClass.class
Hello World, from TestClass
Annotate your implementation classes with a custom annotation and use scannotation it does byte code scanning of the class files, and is orders of magnitudes faster than anything else, you can use it to search the entirety of a very large classpath instantly.