11月24
在平时编码过程中我们都知道要抽象,要封装变化,要实现开闭原则,比如对于很多相似的功能,我们可以将通用的功能抽象出来,然后把变化的不同的地方提取出去,比如模版模式、策略模式等都是实现类似的效果
比如对于策略模式,我们通常是定义一个接口,然后有不同的实现,这种是可以的,但是如果通用流程中要扩展的点较多的话,这些不同的实现也需要管理,可以把他们合并到一个单独的包中,再进一步,我们甚至可以将包单独提取出来,支持运行时加载包实现新增功能的支持
JDK对此功能的支持就是 SPI,但是它的限制较多,也不够灵活,比如dubbo就是自己定义了一套SPI的实现,这次我们来看另一个实现,pf4j 提供一套在基本框架中定义扩展点接口,然后通过不同的插件来实现扩展点的功能,来支持对新增开放对修改关闭
下面我们就来学习一下它的使用
使用
比如我们有一套通用的流程,假设是下单流程,不同的业务线等对于下单都有一些特殊点,但是它们的基本流程是相似的,这时候我们就可以先定义好通用的流程,不同的地方预留出扩展点接口,使用 pf4j 的流程如下
先定义好扩展点接口(需要定义单独的包,因为基本应用和各个扩展点的包都依赖它)
定义单独的插件包,其中实现扩展点接口的功能
在应用中编写基本流程和扩展点的发现使用功能
这次我们就参考 pf4j 提供的例子来看一下
1. 定义扩展点接口
pom.xml首先声明依赖
<dependency>
<groupId>org.pf4j</groupId>
<artifactId>pf4j</artifactId>
<version>3.6.0</version>
<!-- 一般应用中会依赖这个包,所以这里设置为provided即可 -->
<scope>provided</scope>
</dependency>
之后即可声明各个扩展点接口
/**
* 假设我们需要一个通知用户的功能
* 需要注意的是,我们一定要继承 ExtensionPoint 接口,表示这是一个扩展点
*/
public interface Notice extends ExtensionPoint {
boolean notice(List<Long> userIds);
}
比如对于策略模式,我们通常是定义一个接口,然后有不同的实现,这种是可以的,但是如果通用流程中要扩展的点较多的话,这些不同的实现也需要管理,可以把他们合并到一个单独的包中,再进一步,我们甚至可以将包单独提取出来,支持运行时加载包实现新增功能的支持
JDK对此功能的支持就是 SPI,但是它的限制较多,也不够灵活,比如dubbo就是自己定义了一套SPI的实现,这次我们来看另一个实现,pf4j 提供一套在基本框架中定义扩展点接口,然后通过不同的插件来实现扩展点的功能,来支持对新增开放对修改关闭
下面我们就来学习一下它的使用
使用
比如我们有一套通用的流程,假设是下单流程,不同的业务线等对于下单都有一些特殊点,但是它们的基本流程是相似的,这时候我们就可以先定义好通用的流程,不同的地方预留出扩展点接口,使用 pf4j 的流程如下
先定义好扩展点接口(需要定义单独的包,因为基本应用和各个扩展点的包都依赖它)
定义单独的插件包,其中实现扩展点接口的功能
在应用中编写基本流程和扩展点的发现使用功能
这次我们就参考 pf4j 提供的例子来看一下
1. 定义扩展点接口
pom.xml首先声明依赖
<dependency>
<groupId>org.pf4j</groupId>
<artifactId>pf4j</artifactId>
<version>3.6.0</version>
<!-- 一般应用中会依赖这个包,所以这里设置为provided即可 -->
<scope>provided</scope>
</dependency>
之后即可声明各个扩展点接口
/**
* 假设我们需要一个通知用户的功能
* 需要注意的是,我们一定要继承 ExtensionPoint 接口,表示这是一个扩展点
*/
public interface Notice extends ExtensionPoint {
boolean notice(List<Long> userIds);
}
11月24
PF4J是一个Java轻量级的插件框架,可以实现动态加载,执行,卸载外部插件(支持jar以及zip),具体可以看官网:https://pf4j.org/。
本文例子基于Github地址:https://github.com/pf4j/pf4j
<dependency>
<groupId>org.pf4j</groupId>
<artifactId>pf4j</artifactId>
<version>3.6.0</version>
</dependency>
插件项目会涉及到3个工程:工程结构
plugin-api:定义可扩展接口
plugins:插件项目,可以包含多个插件,需要实现plugin-api中定义的接口
plugin-app:主程序,需要依赖plugin-api,加载并执行plugins
定义可扩展接口(plugin-api)
简单定义一个接口,需继承ExtensionPoint:
package plugin.api;
import org.pf4j.ExtensionPoint;
public interface Greeting extends ExtensionPoint {
String getGreeting();
}
实现插件(plugins)
插件需要实现plugin-api定义的接口,并且使用@Extension标记:
package plugins;
import org.pf4j.Extension;
import plugin.api.Greeting;
@Extension
public class WelcomeGreeting implements Greeting {
public String getGreeting() {
return "Welcome";
}
}
插件打包(plugins)
插件打包时,需要往MANIFEST.MF写入插件信息,此处使用maven插件(打包命令为package):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<archive>
<manifestEntries>
<Plugin-Id>welcome-plugin</Plugin-Id>
<Plugin-Version>0.0.1</Plugin-Version>
</manifestEntries>
</archive>
</configuration>
</plugin>
本文例子基于Github地址:https://github.com/pf4j/pf4j
<dependency>
<groupId>org.pf4j</groupId>
<artifactId>pf4j</artifactId>
<version>3.6.0</version>
</dependency>
插件项目会涉及到3个工程:工程结构
plugin-api:定义可扩展接口
plugins:插件项目,可以包含多个插件,需要实现plugin-api中定义的接口
plugin-app:主程序,需要依赖plugin-api,加载并执行plugins
定义可扩展接口(plugin-api)
简单定义一个接口,需继承ExtensionPoint:
package plugin.api;
import org.pf4j.ExtensionPoint;
public interface Greeting extends ExtensionPoint {
String getGreeting();
}
实现插件(plugins)
插件需要实现plugin-api定义的接口,并且使用@Extension标记:
package plugins;
import org.pf4j.Extension;
import plugin.api.Greeting;
@Extension
public class WelcomeGreeting implements Greeting {
public String getGreeting() {
return "Welcome";
}
}
插件打包(plugins)
插件打包时,需要往MANIFEST.MF写入插件信息,此处使用maven插件(打包命令为package):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<archive>
<manifestEntries>
<Plugin-Id>welcome-plugin</Plugin-Id>
<Plugin-Version>0.0.1</Plugin-Version>
</manifestEntries>
</archive>
</configuration>
</plugin>





