Java dynamically loads plugin

I want to create an application that can dynamically load plugins, but I have not found any literature on the Internet.

Difficult thing: I do not know the name in advance.

For example, I have the Plug-in interface:

public interface Plugin { public static Plugin newPlugin(); public void executePlugin(String args[]); } 

So, each class that implements the plugin in the jar file is created in the list:

 Method method = classToLoad.getMethod ("newPlugin"); mylist.add(method.invoke(null); 
  • The first problem is that I cannot have a static method in the interface.
  • The second problem is that I do not know how to find all classes that implement the interface.

Thank you for your help.

+5
source share
2 answers

It looks like you want to dynamically detect classes that implement a specific interface (like Plugin ) at runtime. You have basically two options:

  • Use component infrastructure like osgi
  • Use Java Internal Discovery ( ServiceLoader )

Since there are many good osgi tutorials (also small), I won’t go into detail here. To use the Java internal discovery process, you need to do the following:

  • Link all the “new” classes that you want to open in the jar file.
  • Create a new file inside the jar file: META-INF/services/package.Plugin Here you must use the full package classifier
  • This file is a simple text file and contains the full name of each class that implements Plugin in this jar file
  • Put this jar file in the classpath of your (potentially already running) application
  • Open Services:

Service discovery is performed as follows:

 ServiceLoader<Plugin> loader = ServiceLoader.load(Plugin.class) for (Plugin p : loader) { // do something with the plugin } 

More details here: http://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html

Regarding static methods in interfaces: impossible. The semantics of this will also be somewhat strange, since static methods are available without an instance of the class, and interfaces simply define methods without any functionality. Thus, static allows you to call Interface.doSomething() , while the interface does not define any functionality, this only leads to confusion.

edit:

Added description of what should be in the metafile

+20
source

Regarding your first problem, not being able to use static methods in the interface, my suggestion is to simply use the interface with the marker and instantiate it.

The plugin interface can be simply:

 public interface Plugin { public void executePlugin(String args[]); } 

And then you can do:

 if (someClass instanceOf Plugin) { mylist.add(someClass.newInstance()); } 

This leads to the second question, how do you get someClass link. There is no standard way to find all classes that implement this interface in your class path , although the approach you can do is to check banks in your class path if this file ends in .class determine its full name through the path in jar and use the Class.forName() method to materialize the class.

In the pseudo code, something like this:

 for each jar in your classpath { for each file in JarFile { if (file ends with .class) { materialize class using Class.forName } } } 

With an instance of Class you can check if it implements your Plugin interface.

Also keep in mind that if you need to add some context to your plugins, you can create a constructor in every plugin that gets your context object, instead of having a default constructor. In this case, instead of using newInstance() you will need to get a constructor with the arguments that you would like using reflection.

+2
source

Source: https://habr.com/ru/post/1232770/


All Articles