Getting started 入门指南
It’s very simple to add PF4J in your application:
在您的应用程序中添加 PF4J 非常简单:
public static void main(String[] args) {
...
PluginManager pluginManager = new DefaultPluginManager();
pluginManager.loadPlugins();
pluginManager.startPlugins();
...
}
In above code, I created a DefaultPluginManager (it’s the default implementation for
PluginManager interface) that loads and starts all active(resolved) plugins.
在上述代码中,我创建了一个 DefaultPluginManager(它是 PluginManager 接口的默认实现),用于加载并启动所有激活(已解析)的插件。
Each available plugin is loaded using a different java class loader, PluginClassLoader.
每个可用的插件都使用不同的 java 类加载器加载,即 PluginClassLoader。
The PluginClassLoader contains only classes found in PluginClasspath (default classes and lib folders) of plugin and runtime classes and libraries of the required/dependent plugins. This class loader is a Parent Last ClassLoader - it loads the classes from the plugin’s jars before delegating to the parent class loader.
PluginClassLoader 仅包含插件中找到的类(默认类和 lib 文件夹)以及所需/依赖插件的运行时类和库。这个类加载器是一个父类最后类加载器——它会先从插件的 jar 文件中加载类,然后再委托给父类加载器。
The plugins are stored in a folder. You can specify the plugins folder in the constructor of DefaultPluginManager. If the plugins folder is not specified
then the location is returned by System.getProperty("pf4j.pluginsDir", "plugins")
.
插件存储在一个文件夹中。你可以在 DefaultPluginManager 的构造函数中指定插件文件夹。如果未指定插件文件夹,则返回 System.getProperty("pf4j.pluginsDir", "plugins")
的位置。
NOTE: The “pf4j.pluginsDir” property comes with comma-separated directory list support (support for multiple plugin root directories).
注意:“pf4j.pluginsDir”属性支持逗号分隔的目录列表(支持多个插件根目录)。
The structure of plugins folder is:
插件文件夹的结构如下:
- plugin1.zip (or plugin1 folder)
plugin1.zip(或 plugin1 文件夹) - plugin2.zip (or plugin2 folder)
plugin2.zip(或 plugin2 文件夹)
In plugins folder you can put a plugin as folder or archive file (zip).
A plugin folder has this structure by default:
在插件文件夹中,你可以将插件作为文件夹或归档文件(zip)存放。一个插件文件夹默认具有以下结构:
classes
folderclasses
文件夹lib
folder (optional - if the plugin used third party libraries)
lib
文件夹(可选 - 如果插件使用了第三方库)
The plugin manager searches plugins metadata using a PluginDescriptorFinder.
插件管理器使用 PluginDescriptorFinder 搜索插件元数据。
DefaultPluginDescriptorFinder is a “link” to ManifestPluginDescriptorFinder that lookups plugins descriptors in MANIFEST.MF file.
DefaultPluginDescriptorFinder 是一个“链接”到 ManifestPluginDescriptorFinder,它会在 MANIFEST.MF 文件中查找插件描述符。
In this case the classes/META-INF/MANIFEST.MF
file looks like:
在这种情况下, classes/META-INF/MANIFEST.MF
文件看起来像:
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: decebal
Build-Jdk: 1.6.0_17
Plugin-Class: org.pf4j.demo.welcome.WelcomePlugin
Plugin-Dependencies: x, y, z
Plugin-Id: welcome-plugin
Plugin-Provider: Decebal Suiu
Plugin-Version: 0.0.1
In above manifest I described a plugin with id welcome-plugin
, with class org.pf4j.demo.welcome.WelcomePlugin
, with version 0.0.1
and with dependencies
to plugins x, y, z
.
在上述清单中,我描述了一个具有 id welcome-plugin
、类 org.pf4j.demo.welcome.WelcomePlugin
、版本 0.0.1
以及对插件 x, y, z
的依赖的插件。
NOTE: The plugin version must be compliant with Semantic Versioning (PF4J uses jsemver
as implementation for SemVer because it comes with support for comparing versions)
注意:插件版本必须符合语义化版本控制(PF4J 使用 jsemver
作为语义化版本控制的实现,因为它提供了版本比较的支持)
You can define an extension point in your application using ExtensionPoint interface marker.
您可以使用 ExtensionPoint 接口标记在您的应用程序中定义一个扩展点。
public interface Greeting extends ExtensionPoint {
String getGreeting();
}
Another important internal component is ExtensionFinder that describes how the plugin manager discovers extensions for the extensions points.
另一个重要的内部组件是 ExtensionFinder,它描述了插件管理器如何发现扩展点上的扩展。
DefaultExtensionFinder looks up extensions using Extension annotation.
DefaultExtensionFinder 使用 Extension 注解查找扩展。
DefaultExtensionFinder looks up extensions in all extensions index files META-INF/extensions.idx
. PF4J uses Java Annotation Processing to process at compile time all classes annotated with @Extension and to produce the extensions index file.
DefaultExtensionFinder 在所有扩展索引文件中查找扩展 META-INF/extensions.idx
。PF4J 使用 Java 注解处理在编译时处理所有带有@Extension 注解的类,并生成扩展索引文件。
public class WelcomePlugin extends Plugin {
public WelcomePlugin(PluginWrapper wrapper) {
super(wrapper);
}
@Extension
public static class WelcomeGreeting implements Greeting {
public String getGreeting() {
return "Welcome";
}
}
}
In above code I supply an extension for the Greeting
extension point.
在上面的代码中,我为 Greeting
扩展点提供了一个扩展。
You can retrieve all extensions for an extension point with:
你可以使用以下方式获取一个扩展点的所有扩展:
List<Greeting> greetings = pluginManager.getExtensions(Greeting.class);
for (Greeting greeting : greetings) {
System.out.println(">>> " + greeting.getGreeting());
}
The output is: 输出结果为:
>>> Welcome
>>> Hello
You can inject your custom component (for example PluginDescriptorFinder, ExtensionFinder, PluginClasspath, …) in DefaultPluginManager just override create...
methods (factory method pattern).
Example:
protected PluginDescriptorFinder createPluginDescriptorFinder() {
return new PropertiesPluginDescriptorFinder();
}
and in plugin repository you must have a plugin.properties file with the below content:
plugin.class=org.pf4j.demo.welcome.WelcomePlugin
plugin.dependencies=x, y, z
plugin.id=welcome-plugin
plugin.provider=Decebal Suiu
plugin.version=0.0.1
You can control extension instance creation overriding createExtensionFactory
method from DefaultExtensionFinder.
Also, you can control plugin instance creation overriding createPluginFactory
method from DefaultExtensionFinder.
For more information please see the demo sources.
NOTE: If your application didn’t find extensions then make sure that you have a file with name extensions.idx
generated by PF4J in the plugin jar.
It’s most likely that they are some problems with the annotation processing mechanism from Java.
One possible solution to resolve your problem is to add a configuration to your maven build.
The maven-compiler-plugin
can be configured to do this like so:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<annotationProcessors>
<annotationProcessor>org.pf4j.processor.ExtensionAnnotationProcessor</annotationProcessor>
</annotationProcessors>
</configuration>
</plugin>