记录
在一次玩mc安装mod的过程中,我发现只要将mod的jar包导入mod文件就可以实现加载,并在游戏内部可以实现开启、禁用和删除,于是我就有了一个想法,在自己开发的项目中实现类似的插件化开发,在初步摸索和bing过程中发现了pf4j这个框架,初步实现是可行的,这一篇文章就是他的初步实现,在阅读官方文档过程中我发现了他还有其他框架的集成,其中pf4j-spring引起了我的注意,我了解和ping之后,按照官方文档进行复现,但..........,发现诸多问题,花费了不少时间,关于pf4j-spring下期文章再谈论,那么现在开始实现。
实现
一:环境搭配
构建 PF4J 所需的当前最低 Java 版本应为 9
二:使用工具
maven
idea
三:具体过程
1. 新建项目
使用idea构建一个maven项目,我的命名是Stardye-Plugins-pf4j(星染-插件)。
2. 新建模块
我一般把src文件给删了,新建一个子模块Stardye-Plugins-Service作为插件运行的主类项目,再依次新建两个子模块Stardye-Plugins-Devise(作为插件设计类模块),Stardye-Plugins-Common(作为公共类模块)。
三者maven关系都是平级的,是Stardye-Plugins子模块,但common模块作为依赖项要被其他两个模块引入。
实现在父模块的maven使用<dependencyManagement>管理版本,因为是多模块项目,容易造成版本错误。
<!--父模块Stardye-Plugins-pf4j的maven,实现版本管理 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.stardye.plugins</groupId>
<artifactId>Plugins-Service</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.stardye.plugins</groupId>
<artifactId>Plugins-Devise</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.stardye.plugins</groupId>
<artifactId>Plugins-Common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.pf4j</groupId>
<artifactId>pf4j</artifactId>
<version>3.12.1</version>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 在Plugins-Service和Plugins-Devise模块引入Plugins-Common-->
<dependencies>
<dependency>
<groupId>org.stardye.plugins</groupId>
<artifactId>Plugins-Common</artifactId>
</dependency>
</dependencies>
3. 引入依赖
想必大家都有自己的maven库,在三个模块都添加,或者只在common模块添加,因为其他两个模块需要引入common模块。在这里我因为在父maven中作了版本管理,就将<version>3.12.1</version>给注释掉了。
<dependency>
<groupId>org.pf4j</groupId>
<artifactId>pf4j</artifactId>
<!-- <version>3.12.1</version>-->
</dependency>
4. 具体代码
在common模块中实现接口Greeting接口继承ExtensionPoint,添加方法接口String getGreeting();
import org.pf4j.ExtensionPoint;
public interface Greeting extends ExtensionPoint {
String getGreeting();
}
新建一个Plugins-Devise-Hello模块(开发插件的实现模块)作为Plugins-Devise的子模块。
新添HelloPlugin类继承Plugin,新建HelloGreeting类继承Greeting接口并添加@Extension注解。
import org.pf4j.Plugin;
public class HelloPlugin extends Plugin {
public HelloPlugin() {
super();
}
@Override
public void start() {
System.out.println("HelloPlugin start");
super.start();
}
@Override
public void stop() {
System.out.println("HelloPlugin stop");
super.stop();
}
@Override
public void delete() {
System.out.println("HelloPlugin delete");
super.delete();
}
}
import org.pf4j.Extension;
@Extension
public class HelloGreeting implements Greeting{
@Override
public String getGreeting() {
return "Hello 插件成功实现扩展";
}
}
Plugins-Devise-Hello模块的resources中添加plugin.properties文件,必须有一个包含以下内容的 plugin.properties 文件,然后打包。最后在Stardye-Plugins-Service项目添加一个plugins文件,具体路径自己设置,新建Main类,添加以下代码,其中pluginsPath是你的plugins文件文件路径,在启动之前要记得将打包的Hello插件的jar移动或复制进去。
import org.pf4j.DefaultPluginManager;
import org.pf4j.PluginManager;
import java.nio.file.Paths;
import java.util.List;
public class Main {
public static void main(String[] args) {
String pluginsPath = "D:\\importants\\Project\\git\\Stardye-Plugins-pf4j\\Plugins-Service\\plugins";
PluginManager pluginManager = new DefaultPluginManager(Paths.get(pluginsPath));
pluginManager.loadPlugins();
pluginManager.startPlugins();
List<Greeting> greetings = pluginManager.getExtensions(Greeting.class);
System.out.println("greetings: " + greetings.size());
for (Greeting greeting : greetings) {
System.out.println(greeting.getGreeting());
}
}
}
5. 重点问题
如果无法输出"Hello 插件成功实现扩展",代表扩展失败,即如果您的应用程序没有找到扩展,请确保插件 jar 中有一个名称为 PF4J 的文件。 它们很可能是 Java 的 Comments 处理机制存在一些问题。 解决问题的一种可能解决方案是将配置添加到您的 maven 构建中。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<annotationProcessors>
<annotationProcessor>org.pf4j.processor.ExtensionAnnotationProcessor</annotationProcessor>
</annotationProcessors>
</configuration>
</plugin>
</plugins>
</build>