Administrator
Published on 2024-11-26 / 44 Visits
0
0

学习pf4j框架开发可拔插系统系列(一)

记录

在一次玩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>


Comment