PF4J使用
PF4J是一个Java轻量级的插件框架,可以实现动态加载,执行,卸载外部插件(支持jar以及zip),具体可以看官网:https://pf4j.org/。
本文例子基于Github地址:https://github.com/pf4j/pf4j
<dependency>
<groupId>org.pf4j</groupId>
<artifactId>pf4j</artifactId>
<version>3.0.1</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上介绍,MANIFEST.MF中Plugin-Id以及Plugin-Version是必须信息:
In above manifest I described a plugin with id
welcome-plugin(mandatory attribute), with classorg.pf4j.demo.welcome.WelcomePlugin(optional attribute), with version0.0.1(mandatory attribute) and with dependencies to pluginsx, y, z(optional attribute).
此处定义插件ID为welcome-plugin,版本为0.0.1
加载执行插件(plugin-app)
package plugin.app;
import java.nio.file.Paths;
import java.util.List;
import org.pf4j.JarPluginManager;
import org.pf4j.PluginManager;
import plugin.api.Greeting;
public class Main {
public static void main(String[] args) {
// jar插件管理器
PluginManager pluginManager = new JarPluginManager();
// 加载指定路径插件
pluginManager.loadPlugin(Paths.get("plugins-0.0.1-SNAPSHOT.jar"));
// 启动指定插件(也可以加载所有插件)
pluginManager.startPlugin("welcome-plugin");
// 执行插件
List<Greeting> greetings = pluginManager.getExtensions(Greeting.class);
for (Greeting greeting : greetings) {
System.out.println(">>> " + greeting.getGreeting());
}
// 停止并卸载指定插件
pluginManager.stopPlugin("welcome-plugin");
pluginManager.unloadPlugin("welcome-plugin");
}
}
运行输出:
>>> Welcome
其他
插件周期
如果对插件生命周期(如加载,执行,停止等)有兴趣的话,可以实现插件类继承Plugin:
package plugins;
import org.pf4j.Plugin;
import org.pf4j.PluginWrapper;
public class WelcomePlugin extends Plugin {
public WelcomePlugin(PluginWrapper wrapper) {
super(wrapper);
}
@Override
public void start() {
System.out.println("WelcomePlugin.start()");
}
@Override
public void stop() {
System.out.println("WelcomePlugin.stop()");
}
@Override
public void delete() {
System.out.println("WelcomePlugin.delete()");
}
}
同时往MANIFEST.MF写入插件信息:
<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>
<!-- 新增 -->
<Plugin-Class>plugins.WelcomePlugin</Plugin-Class>
</manifestEntries>
</archive>
</configuration>
</plugin>
打包后运行输出:
WelcomePlugin.start()
>>> Welcome
WelcomePlugin.stop()
如果对运行流程感兴趣,或者调试,可以将日志级别设为debug日志
log4j.properties示例:
log4j.rootLogger = debug,stdout,log
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %d [%-5p] %l %r ms: %m%n
log4j.appender.log = org.apache.log4j.DailyRollingFileAppender
log4j.appender.log.DatePattern = _yyyy-MM-dd
log4j.appender.log.File = logs/debug.log
log4j.appender.log.Encoding = UTF-8
log4j.appender.log.layout = org.apache.log4j.PatternLayout
log4j.appender.log.layout.ConversionPattern = %d [%-5p] (%c.%t): %m%n
PF4J使用的更多相关文章
- pf4j实例 插件框架
实现整个过程需要三个部分,第一就是根接口,第二是插件,第三是应用程序.这是3个java项目. 首先要下载jar包,百度搜索maven repository,然后搜索pf4j,如下图,下载第一个的相应版 ...
- pf4j及pf4j-spring
什么是PF4J 一个插件框架,用于实现插件的动态加载,支持的插件格式(zip.jar). 核心组件 Plugin:是所有插件类型的基类.每个插件都被加载到一个单独的类加载器中以避免冲突. Plugin ...
- Gitblit-Git版本服务器环境部署
Gitblit介绍 Gitblit 是一个纯 Java 库用来管理.查看和处理 Git 资料库.相当于 Git 的 Java 管理工具,支持linux系统. Git是分布式版本控制系统,它强调速度.数 ...
- mac osx App store 安装软件 发生错误
app store 安装软件时发生错误 解决办法: 1. 进入如下目录: sh-3.2# cd Library/Application\ Support/App\ Store/ sh-3.2# pwd ...
- 【原创】插件式ICE服务框架
Zero ICE在跨平台.跨语言的环境中是一种非常好的RPC方案,而且使用简单.早期在使用ICE时,每一个后端功能模块都以独立服务方式部署,在功能模块较少时不会有明显的问题,但是随着功能模块的增多,部 ...
- iot平台异构对接文档
iot平台异构对接文档 准备工作 平台提供的XAgent开发指南.pdf demo程序xagent-ptp-demo 平台上添加产品得到产品id和key 部署时需要插件的基础程序<xlink-x ...
- 透过现象看本质:Java类动态加载和热替换
摘要:本文主要介绍类加载器.自定义类加载器及类的加载和卸载等内容,并举例介绍了Java类的热替换. 最近,遇到了两个和Java类的加载和卸载相关的问题: 1) 是一道关于Java的判断题:一个类被首次 ...
- 服务器程序动态加载自定义jar包的过程
需求: 用过hive的都知道,可以自定义hive的一个udf jar,然后将这个jar add到hive服务端,就会加载这个jar实现用户自定义逻辑.现在的需求就是实现这么一个服务端所做的事情! 场景 ...
随机推荐
- Docker Harbor私有仓库部署与管理 (超详细配图)
Docker Harbor私有仓库部署与管理 1.Harbor 介绍 2.Harbor部署 3.Harbor管理 1.Harbor 介绍: 什么是 Harbor ? Harbor 是 VMware 公 ...
- 啥叫IP地址及子网掩码?
啥叫IP地址及子网掩码 ??? 1.IP地址的定义及分类 1.1IP地址的定义 1.2IP地址的分类 2.子网掩码 1.1 互联网上连接的网络设备和计算机都有唯一的地址,此作为该主机在Interne ...
- mysql表查询、多表查询(增强查询的使用)子查询、合并查询,外连接,mysql5种约束,自增长
一.查询加强 1.在mysql中,日期类型可以直接比较,需要注意格式 2.%:表示0到多个字符, _:表示单个字符 exp:显示第二个字符为大写O的所有员工的姓名和工资 select name fr ...
- 基于双TMS320C6678 DSP的3U VPX的信号处理平台
一.板卡概述 板卡由我公司自主研发,基于3U VPX架构,处理板包含两片TI DSP TMS320C6678芯片:一片Xilinx公司的Spartan XC3S200AN 配置芯片: DSP之间通过 ...
- 非极大值抑制算法(Python实现)
date: 2017-07-21 16:48:02 非极大值抑制算法(Non-maximum suppression, NMS) 算法原理 非极大值抑制算法的本质是搜索局部极大值,抑制非极大值元素. ...
- Solution -「APIO 2018」「洛谷 P4630」铁人两项
\(\mathcal{Description}\) Link. 给定一个 \(n\) 个点 \(m\) 条边的无向图(不保证联通),求有序三元点对 \((s,c,f)\) 的个数,满足 \(s ...
- suse 12 部署chrony时间同步服务器
文章目录 1.ntp和chrony的区别 1.1.关于chrony 1.2.chronyd的优势 2.环境介绍 3.部署chrony 4.配置chrony 4.1.配置文件解析 4.2.查看chron ...
- 操作系统实验一:进程管理(含成功运行C语言源代码)
目录 操作系统实验一:进程管理 1.实验目的 2.实验内容 3.实验准备 3.1.1进程的含义 3.1.2进程的状态 3.1.3进程状态之间的转换 3.2 进程控制块PCB 3.2.1进程控制块的作用 ...
- Spring是什么? 核心总结
Spring是一个开源框架,它由Rod Johnson创建.它是为了解决企业应用开发的复杂性而创建的. Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情. 然而,Spring ...
- ios开发 将json格式数据上传服务器
看了一些大小牛的资料其实就3步 1.使用post 请求 ,因为get是不能上传的 2.设置请求类型 , 讲你的json数据上传 3.向服务器发送数据按照下面示例代码,就差不多了 1 // 1.创建请求 ...