使用PF4J实现插件化系统-入门

    xiaoxiao2023-09-12  285

    在进行业务平台型系统开发时,常常遇到接口大致相同,但是不同的业务的场景,其实现却有所不同。在分工方面,不同的业务场景,可能是不同的开发人员。这时就可以通过插件化的方式,针对不同的业务场景,实现不同的插件,来满足业务的需求。

    PF4J是一个Java轻量级的插件框架,使用PF4J可以轻松的将一个Java应用转成一个插件化的应用。其拥有最小的依赖关系和很强的扩展性。

    <dependency> <groupId>ro.fortsoft.pf4j</groupId> <artifactId>pf4j</artifactId> <version>${pf4j.version}</version> </dependency>

    目前pf4j的最新是1.3.0。以下示例我们都以这个版本为例。

    工程结构

    pf4j-plugin-demo

    插件化的工程结构如上:

    api:定义可扩展的接口,其他插件实现这里所定义的接口。在实际的工程中,定义可扩展点的接口是比较难的地方app:运行程序,这里是程序的入口。插件直接拷贝至指定的目录,app就可以找到指定的插件plugins:插件模块,这里实现api中所定义的接口。在实际的工程中,这部分可以是单独的代码库,其依赖api以及项目的一些基础模块定义可扩展接口

    我们先来定义api的接口

    public interface Greeting extends ExtensionPoint { String message(String name); }

    这里我们定义了一个Greeting接口。

    以上我们继承了ExtensionPoint接口,用于标记这个接口是提供一个扩展点。PF4J任何在接口和抽象类都可以继承它。

    实现插件

    接下来我们实现插件

    public class ChinesePlugin extends Plugin { private static final Logger logger= LoggerFactory.getLogger(ChinesePlugin.class); public ChinesePlugin(PluginWrapper wrapper) { super(wrapper); } @Override public void start() throws PluginException { System.out.println("Chinese plugin start."); super.start(); } @Override public void stop() throws PluginException { logger.info("Chinese plugin stop."); super.stop(); } }``` 在实现插件时,首先我们继承Plugin类,实现其start和stop接口。在PluginManager加载完成之后,调用startPlugins就会执行这里的start方法。

    @Extensionpublic class ChineseGreeting implements Greeting {

    @Override public String message(String name) { return "你好," + name; }

    }`以上就实现了中文版的插件。

    同样英文版插件如下:

    public class EnglishPlugin extends Plugin { public EnglishPlugin(PluginWrapper wrapper) { super(wrapper); } @Override public void start() throws PluginException { System.out.println("English plugin start."); super.start(); } @Override public void stop() throws PluginException { System.out.println("English plugin start."); super.stop(); } } @Extension public class EnglishGreeting implements Greeting { @Override public String message(String name) { return "Hi," + name; } }``` 插件打包 在插件编写完成之后,需要打包和进行版本管理。PF4j支持zip包的方式,在zip包中有classes和lib两个目录,classes中为插件的class文件,lib为插件依赖的第三方包。在maven中,我们可以使用maven-assembly插件,打出zip包。具体配置可下载demo代码查看。 插件加载、启动 public static void main(String[] args) { //使用默认的插件管理器 PluginManager pluginManager = new DefaultPluginManager(new File("/app/plugins").toPath()); //加载插件 pluginManager.loadPlugins(); //启动插件 pluginManager.startPlugins(); //获取所有的Greeting的扩展实现 List<Greeting> greetings = pluginManager.getExtensions(Greeting.class); for (Greeting greeting : greetings) { System.out.println( greeting.message("yywang")); } }```

    在以上代码中,我们使用了DefaultPluginManager插件管理器,在实际使用中,也可以自己是插件管理器。在这里我们读取/app/plugins目录下的所有的插件。

    第二步,加载插件。这里会把所有的插件的Class加载到PluginClassLoader中,为避免冲突,每个插件都有自己的PluginClassLoader。

    第三步,启动插件。这里很简单就是把所有的插件调用start方法,启动插件,并且把插件的状态设置成STARTED

    第四步,运行插件。这里我们通过获取所有Greeting的实现运行插件。pluginManager还有一些其他接口,满足我们不同的业务场景。

    运行

    对以上插件进行打包,并把插件拷贝至指定的目录,运行以上main方法,结果如下

    >>> 你好,yywang >>> Hi,yywang``` 以上就是一个关于PF4J的入门,后面我们还会深入了解,如何定义插件管理、插件版本管理、插件生命周期、开发模式和线上模式等等。 相关资源:java软件插件开发模式源码
    最新回复(0)