如何打包 Ark Plugin

本样例工程演示如何借助 Maven 插件,将一个普通的 Java 工程打包成标准格式规范的 Ark Plugin。

背景信息

实际开发中,常常会遇到依赖包冲突的情况。假设开发了一个类库 sample-lib,业务应用在引入使用时,可能存在跟已有的依赖发生冲突的情况。此时,开发者需要自己的类库能够和业务其他依赖进行隔离,互不协商双方依赖包版本。Ark Plugin 正是基于这种需求背景下的实践产物。

Ark Plugin 运行在 Ark Container 之上,由容器负责加载启动。任何一个 Ark Plugin 由独立的 ClassLoader 加载,从而做到相互隔离。Ark Plugin 存在四个概念:

  • 导入类:插件启动时,优先委托给导出该类的插件负责加载,如果加载不到,才会尝试从本插件内部加载。

  • 导出类:其他插件如果导入了该类,优先从本插件加载。

  • 导入资源:插件在查找资源时,优先委托给导出该资源的插件负责加载,如果加载不到,才会尝试从本插件内部加载。

  • 导出资源:其他插件如果导入了该资源,优先从本插件加载。

有关插件规范的信息,请参见 插件规范

使用工具

SOFAArk 默认提供了 Maven 插件 sofa-ark-plugin-maven-plugin,您只需通过简单的配置,即可将普通的 Java 工程打包成标准格式规范的 Ark Plugin,插件坐标为:

<plugin>
    <groupId>com.alipay.sofa</groupId>
    <artifactId>sofa-ark-plugin-maven-plugin</artifactId>
    <version>${sofa.ark.version}</version>
</plugin>

有关插件配置的信息,请参见 完整配置模板

操作步骤

  1. 创建标准 Maven 工程。

    该用例工程是一个标准的 Maven 工程,一共包含两个模块:

    • common 模块:包含了插件导出类。

    • plugin 模块:包含了com.alipay.sofa.ark.spi.service.PluginActivator接口实现类和一个插件服务类,插件打包工具 sofa-ark-plugin-maven-plugin 即配置在该模块的 pom.xml 中。

  2. 配置打包插件。

    在 plugin 模块的pom.xml中配置打包插件,示例如下:

    <build>
        <plugins>
            <plugin>
                <groupId>com.alipay.sofa</groupId>
                <artifactId>sofa-ark-plugin-maven-plugin</artifactId>
                <version>${project.version}</version>
                <executions>
                    <execution>
                        <id>default-cli</id>
                        <goals>
                            <goal>ark-plugin</goal>
                        </goals>
    
                        <configuration>
    
                        <!--can only configure no more than one activator-->
                        <activator>com.alipay.sofa.ark.sample.activator.SamplePluginActivator</activator>
    
                        <!-- configure exported class -->
                        <exported>
                            <!-- configure package-level exported class-->
                            <packages>
                                <package>com.alipay.sofa.ark.sample.common</package>
                            </packages>
    
                             <!-- configure class-level exported class -->
                            <classes>
                                <class>com.alipay.sofa.ark.sample.facade.SamplePluginService</class>
                            </classes>
                        </exported>
    
                        <!--specify destination where ark-plugin will be saved, default saved to ${project.build.directory}-->
                        <outputDirectory>../target</outputDirectory>
    
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    

    示例工程中,虽只配置了一部分配置项,但已经足够生成一个可用的 Ark Plugin。各配置项含义如下:

    • activator:Ark 容器启动插件的入口类,最多只能配置一个。

      在插件的 activator 中,通常会执行一些初始化操作,比如发布插件服务。在本样例工程中,即发布了插件服务。

    • 导出包:包级别的导出类配置。插件中所有以导出包名为前缀的类,包括插件的三方依赖包,都会被导出。

    • 导出类:精确类名的导出类配置,导出具体的类。

    • outputDirectory:使用mvn package 命令打包后,输出的 Ark Plugin 文件存放目录。

    在示例工程中,只导出了工程创建的类。实际在使用时,也可以把工程依赖的三方包也导出去。

  3. 打包、安装、发布、引入 Ark Plugin。

    和普通的工程操作类似,您可以使用mvn packagemvn installmvn deploy 完成插件包的安装和发布。

    重要

    默认发布的 Ark Plugin,其 Maven 坐标会增加 classifier=ark-plugin。例如在该样例工程中,如果需要使用该 Ark Plugin,必须如下配置依赖:

    <dependency>
        <groupId>com.alipay.sofa</groupId>
        <artifactId>sample-ark-plugin</artifactId>
        <classifier>ark-plugin</classifier>
        <version>${sofa.ark.version}</version>
    </dependency>
  4. 发布引用插件服务。

    以下示例工程中,演示了如何使用PluginContext发布插件服务:

    public class SamplePluginActivator implements PluginActivator{
    
        public void start(PluginContext context) throws ArkRuntimeException{
            System.out.println("starting in sample ark plugin activator");
            context.publishService(SamplePluginService.class,new SamplePluginServiceImpl());
        }
    
        public void stop(PluginContext context)throws ArkRuntimeException{
            System.out.println("stopping in ark plugin activator");
        }
    }

    同时,在服务实现SamplePluginServiceImpl中演示了如何引用其他插件或者 Ark 容器发布的服务。此处引用 Ark 容器发布的事件管理服务EventAdminService

    public class SamplePluginServiceImpl implements SamplePluginService {
    
        @ArkInject
        private EventAdminService eventAdminService;
    
        public String service() {
            return "I'm a sample plugin service published by ark-plugin";
        }
    
        public void sendEvent(ArkEvent arkEvent) {
            eventAdminService.sendEvent(arkEvent);
        }
    }