-
Notifications
You must be signed in to change notification settings - Fork 127
Concept Plugin
Linyuzai edited this page Apr 8, 2022
·
32 revisions
目前主要用于动态加载外部jar
中的Class
当我们遇到一些插件化的需求时可能就会想到通过如动态加载类的方式来实现
java
中自带有spi
,不过功能有限,是以类加载作为基础概念
而本库是以插件作为基础概念,类加载作为一种插件的具体实现方式
插件可以是一个jar
文件,一段java
代码,一个Excel
文件...
由于jar
文件相对java
来说可能更适合作为插件的载体
所以具体实现了jar
文件作为插件
public class ConceptPluginSample {
/**
* 插件提取配置
*/
private final JarPluginConcept concept = new JarPluginConcept.Builder()
//添加类提取器
.addExtractor(new ClassExtractor<Class<? extends CustomPlugin>>() {
@Override
public void onExtract(Class<? extends CustomPlugin> plugin) {
//回调
}
})
.build();
/**
* 加载一个 jar 插件
*
* @param filePath jar 文件路径
*/
public void load(String filePath) {
concept.load(filePath);
}
}
创建一个JarPluginConcept
并添加一个类提取器ClassExtractor
,指定提取CustomPlugin.class
或是其子类
调用load
方法传入文件地址就会回调jar
中匹配到的类,如果没有匹配到则不会触发回调
当然如果存在多个符合条件的Class
可以直接指定集合类型
public class ConceptPluginSample {
/**
* 插件提取配置
*/
private final JarPluginConcept concept = new JarPluginConcept.Builder()
//添加类提取器
.addExtractor(new ClassExtractor<List<Class<? extends CustomPlugin>>>() {
@Override
public void onExtract(List<Class<? extends CustomPlugin>> plugin) {
//回调
}
})
.build();
}
implementation 'com.github.linyuzai:concept-plugin-jar:1.0.0'
<dependency>
<groupId>com.github.linyuzai</groupId>
<artifactId>concept-plugin-jar</artifactId>
<version>1.0.0</version>
</dependency>
类型 | 说明 | 数据结构 |
---|---|---|
类 | 支持提取Class
|
Map<String, Class<CustomPlugin>> List<Class<CustomPlugin>> Set<Class<CustomPlugin>> Collection<Class<CustomPlugin>> Class<CustomPlugin>[] Class<CustomPlugin>
|
实例 | 支持提取实例,支持能够使用无参构造器实例化的类 |
Map<String, CustomPlugin> List<CustomPlugin> Set<CustomPlugin> Collection<CustomPlugin> CustomPlugin CustomPlugin[]
|
Properties 文件 |
支持提取后缀为.properties 的文件 |
Map<String, Properties> List<Properties> Set<Properties> Collection<Properties> Properties[] Properties Map<String, Map<String, String>> List<Map<String, String>> Set<Map<String, String>> Collection<Map<String, String>> Map<String, String>[] Map<String, String>
|
任意文件内容 | 支持提取任意的文件内容(jar 中会排除.class 和.properties ) |
Map<String, byte[]> List<byte[]> Set<byte[]> Collection<byte[]> byte[][] byte[] Map<String, InputStream> List<InputStream> Set<InputStream> Collection<InputStream> InputStream[] InputStream Map<String, String> List<String> Set<String> Collection<String> String[] String |
插件对象 | 可以获得类加载器,URL 等数据 |
Plugin JarPlugin
|
上下文 | 插件加载时的中间数据等 | PluginContext |
当使用Map
时,对应的key
将返回文件的路径和名称,如com/github/linyuzai/concept/sample/plugin/CustomPluginImpl.class
支持泛型写法
List<Class<? extends CustomPlugin>>
Set<? extends CustomPlugin>
- ...
动态匹配可以支持任意类型与数量的插件匹配
public class ConceptPluginSample {
/**
* 插件提取配置
*/
private final JarPluginConcept concept = new JarPluginConcept.Builder()
//添加类提取器
.extractTo(this)
.build();
@OnPluginExtract
public void onPluginExtract(Class<? extends CustomPlugin> pluginClass, Properties properties) {
//任意一个参数匹配上都会触发回调
}
/**
* 加载一个 jar 插件
*
* @param filePath jar 文件路径
*/
public void load(String filePath) {
concept.load(filePath);
}
}
当我们既要获得某些指定的类又想要同时获得配置文件(假设包里定义了一个properties
文件)
可以直接定义一个方法,设置参数为我们需要提取的类和配置文件,再在方法上标注@OnPluginExtract
然后使用extractTo
将定义了上述方法的对象传入就行了
动态匹配还提供了更精准化的注解配置
注解 | 说明 |
---|---|
@PluginPath |
路径匹配 |
@PluginName |
名称匹配 |
@PluginProperties |
properties 文件匹配 |
@PluginPackage |
包名匹配 |
@PluginClassName |
类名匹配 |
@PluginClass |
类匹配 |
@PluginAnnotation |
类上注解匹配 |
其中@PluginProperties
可以单独指定key
-
@PluginProperties("concept-plugin.a")
可以直接得到对应的String
值(只能是String
没有做类型转换) -
@PluginProperties("concept-plugin.map.**")
可以获得concept-plugin.map
为前缀的Map<String, String>
由于匹配字符串使用的都是Spring
中的AntPathMatcher
,所有注解都支持通配符,如@PluginPackage("com.github.linyuzai.concept.**.plugin")