# 插件结构

一个Sermant插件主要由以下模块组成:

  • 插件主模块(plugin),该模块主要用于声明字节码增强逻辑
  • 插件服务模块(service),该模块用于辅助插件主模块完成增强逻辑,比如添加动态配置监听器等(非必要模块)

通过在pom文件的properties中指定package.plugin.type的值确定模块类型,plugin表示该模块为插件主模块,service表示该模块为插件服务模块。插件中可包含多个插件主模块和插件服务模块。

基于Sermant良好的类加载器设计,在插件主模块(plugin)中,可以通过compile方式引入第三方依赖,而不会引发与宿主应用的类冲突问题,但是开发者如果需要在插件中使用宿主类,则不建议在plugin模块通过compile方式引入该类所在的依赖,如果需要,可在service模块引入,并在plugin模块中调用service模块的实现,下文将介绍使用方式。

# 插件主模块

插件主模块是插件的主要实现,开发者需要在该模块中声明该插件的增强逻辑增强逻辑开发可参考字节码增强章节。

# 插件服务模块

插件服务模块插件主模块相比:

  • 用于编写插件主模块无法实现的增强逻辑
  • 允许通过compile方式自由添加所需的第三方依赖。

注意:若需引入插件主模块,需以provided形式在其pom中引入。

# 插件服务

插件服务主要分为两部分:

服务接口定义插件主模块中用于描述该服务提供的能力,在定义插件的插件服务时,需要继承插件服务基础接口io.sermant.core.plugin.service.PluginService (opens new window),该接口提供的start()方法会在Sermant启动时被调用,stop()方法会在JVM停止时被调用。

服务接口实现插件服务模块中,在插件主模块中可以通过SPI机制加载并使用插件服务的接口实现。

# 开发示例

本开发示例基于创建首个插件文档中创建的工程。

注:该开发示例下描述的插件服务接口及其实现已在模板工程中存在,可直接使用,无需重复创建,本示例详细描述其创建过程可以使开发者更易于理解开发过程。

在开发插件服务时,首先需要在插件主模块中定义插件服务的接口,这是使用插件服务时的索引,在工程中template\template-plugin下创建com.huaweicloud.sermant.template.EchoService接口,并在其中定义echo接口方法:

public interface EchoService extends PluginService {
    void echo(String string);
}

接口定义完成后,需要在插件服务模块提供上述接口的实现,来执行实际的逻辑,在工程中template\template-service中创建com.huaweicloud.sermant.template.EchoServiceImpl类,其需要实现com.huaweicloud.sermant.template.EchoService接口,并实现接口中定义的echo接口方法:

public class EchoServiceImpl implements EchoService {
    @Override
    public void echo(String string) {
        // 回应别人的问候
        string = string.replaceAll("[\\pP+~$`^=|<>~`$^+=|<>¥×]", "");
        System.out.println("ECHO: " + string + " to you!");
    }
}

开发插件服务的最后,不要忘记添加插件服务的SPI配置,在工程中template\template-service下的资源目录resources中添加META-INF/services目录,并在其中创建名为io.sermant.core.plugin.service.PluginServiceSPI文件,并向其中添加插件服务实现类的类名:

com.huaweicloud.sermant.template.EchoServiceImpl

接下来,找到工程中template\template-plugin下的com.huaweicloud.sermant.template.TemplateDeclarer类,在针对main方法的拦截器before方法中使用已经开发完成的插件服务,通过io.sermant.core.plugin.service.PluginServiceManager (opens new window)插件服务管理器获取插件服务并使用:

注:io.sermant.core.plugin.service.PluginServiceManager::getPluginService(Class clazz)可通过插件服务接口基于Java SPI机制获取插件服务实现的实例。

public ExecuteContext before(ExecuteContext context) throws Exception {
    System.out.println("Good morning!");
    PluginServiceManager.getPluginService(EchoService.class).echo("Good morning!");
    return context;
}

开发完成后,可参照创建首个插件时的打包构建流程,在工程根目录下执行 mvn package,执行完成后在根目录执行 cd agent/,并在其中携带Sermant运行测试应用,执行如下命令 java -javaagent:sermant-agent.jar -jar Application.jar

$ java -javaagent:sermant-agent.jar -jar Application.jar
[xxxx-xx-xxTxx:xx:xx.xxx] [INFO] Loading god library into BootstrapClassLoader.
[xxxx-xx-xxTxx:xx:xx.xxx] [INFO] Building argument map by agent arguments.
[xxxx-xx-xxTxx:xx:xx.xxx] [INFO] Loading core library into SermantClassLoader.
[xxxx-xx-xxTxx:xx:xx.xxx] [INFO] Loading sermant agent, artifact is: default
[xxxx-xx-xxTxx:xx:xx.xxx] [INFO] Load sermant done, artifact is: default
Good morning!
ECHO: Good morning to you!

可以看到,招呼得到了回应,我们创建的插件服务已经生效了,如需要开发新的插件服务,按照上述开发示例执行即可。

上次更新: 2024/5/16 02:26:27