插件化PF4J学习记录

2020-04-04

PF4J 学习记录

什么是PF4J?

Plugin Framework for Java
PF4J 是一个java语言的、开源的、轻量级的的插件框架,只需要很少的一些依赖(slf4j-apijava-semver(Java implementation of the SemVer Specification)
通过使用pf4j,可以很容易的在单体应用模块化应用之间切换。

核心组件:

  • ExtensionPoint,代表程序中可被调用的自定义代码, 任意接口或者抽象类都可被标注为扩展点,实现ExtensionPoint接口即可。
  • Extension是一个ExtensionPoint扩展点的实现,是一个Java Annotation
  • Plugin 所有插件类型的基类,每一个插件都会通过一个独立的类加载器进行加载,以防止冲突发生。
  • PluginManager 用来管理插件的各种功能(加载、启动、停止等),你可以使用DefaultPluginManager作为内置的默认实现,或者你也可以通过实现AbstractPluginManager自定义实现,只需要实现一个工厂方法。
  • PluginLoader 用来加载插件所需要的所有信息(classes)

Get Started

在应用程序中添加pf4j是非常容易的,如下:

1
2
3
4
5
6
7
8
9
public static void main(String[] args) {
...

PluginManager pluginManager = new DefaultPluginManager();
pluginManager.loadPlugins();
pluginManager.startPlugins();

...
}

每一个有效的插件都会由不同的类加载器加载,通过PluginClassLoaderPluginClassLoader仅包含从PluginClasspath(默认为插件目录结构classes目录以及lib目录下)、运行时类以及运行时所请求和依赖的插件中加载信息,会在委托给父类加载器之前通过读取插件的jar包加载。
插件的存储结构:

  • plugin1.zip
  • plugin1 文件夹
    • classes
    • lib(可选项,存储插件中使用到的三方库)

插件管理器通过使用PluginDescriptorFinder查找插件元数据。
DefaultPluginDescriptorFinder是一个指向ManifestPluginDescriptorFinder,是用来找到manifest.mf文件的跳转。classes/META-INF/MANIFEST.MF如下:

1
2
3
4
5
6
7
8
9
10
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: isaac
Build-Jdk: 1.8.0_42
Plugin-Class: org.pf4j.demo.welcome.WelcomePlugin
Plugin-Dependencies: x, y, z
Plugin-Id: welcome-plugin
Plugin-Provider: Isaac Zhang
Plugin-Version: 0.0.1

上述结构中有几点需要注意:

  • Plugin-Id
  • Plugin-Class
  • Plugin-Version
  • Plugin-Dependencies
技术 优势 劣势 现状
自定义实现插件机制,在SpringContext加载之前注入插件信息(classes) 可自由发挥 上手有一定技术难度 demo已实现,插件可以读取主程序类信息
pf4j 理解简单,方便扩展,不局限于Spring 不支持热插拔,在研究中 demo 已实现
pf4j-spring 1. 编码简单 2. 有社区支持 1. 不支持热插拔 2. 受限于spring demo已实现