Skip to content

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")

插件自动加载

插件加载流程

插件提取器

插件过滤器

插件解析器

动态解析

插件匹配器

插件转换器

插件格式器

插件事件

插件类加载器

插件需要依赖其他jar时的注意事项

Clone this wiki locally