# 创建首个插件

本文用于指导如何在本地开发你的第一个插件。

# 开发环境

# 基于Archetype模版创建项目

# 生成项目

本地执行如下Maven指令:

$ mvn archetype:generate -DarchetypeGroupId=io.sermant -DarchetypeArtifactId=sermant-template-archetype -DarchetypeVersion=2.1.0 -DgroupId=io.sermant -Dversion=2.1.0 -Dpackage=io.sermant -DartifactId=first-plugin

执行上述指令后,出现下述日志后回车进行确认:

[INFO] Using property: groupId = io.sermant
[INFO] Using property: artifactId = first-plugin
[INFO] Using property: version = 2.1.0
[INFO] Using property: package = io.sermant
Confirm properties configuration:
groupId: io.sermant
artifactId: first-plugin
version: 2.1.0
package: io.sermant
 Y: :

出现下述成功提示日志,则通过Archetype模版创建项目成功:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  5.409 s
[INFO] Finished at: 2024-12-01T15:10:05+08:00
[INFO] ------------------------------------------------------------------------

# 工程结构

基于Archetype生成的模板工程目录如下:

.
├── application
├── config
└── template
    ├── config
    ├── template-plugin
    └── template-service

application:为测试应用模块,该模块用于测试模板中已定义的插件是否能够生效,正式进行项目开发时可清理。

config:为Sermant的配置目录。

template:template插件模块,此处进行插件能力的开发。

template\template-plugin:template插件的主模块,参考插件主模块

template\template-service:template插件的服务模块,参考插件服务模块

# 开发插件

首先找到模板工程template\template-plugin下的io.sermant.template.TemplateDeclarer类,我们可以在其中声明我们期望增强的类,指定该类中我们期望增强的方法,并为其定义增强逻辑。

# 声明需增强的类

指定期望增强的类,需在io.sermant.template.TemplateDeclarer中的getClassMatcher()方法实现如下逻辑:

  1. 定义类匹配器ClassMatcher.nameEquals("io.sermant.demo.template.Application"),该匹配器通过类名称匹配io.sermant.demo.template.Application类。
@Override
public ClassMatcher getClassMatcher() {
		return ClassMatcher.nameEquals("io.sermant.demo.template.Application");
}

注:上述逻辑已在模版代码中实现

io.sermant.demo.template.Application逻辑如下:

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
        greeting();
    }
    private static void greeting() {
        System.out.println("Good afternoon!");
        SimulateServer.handleRequest(new HashMap<>());
    }
}

我们将通过该插件在greeting方法前后增加System.out.println("Good morning!")System.out.println("Good night!")逻辑。

# 声明需增强的方法

指定需要增强的类后,需要指定该类中你期望增强的方法,并为该方法定义增强逻辑,上述步骤需要在io.sermant.template.TemplateDeclarer中的getInterceptDeclarers(ClassLoader classLoader)方法中指定方法匹配器和拦截器:

  1. 定义一个方法匹配器MethodMatcher.nameEquals("greeting"),该匹配器通过方法名称匹配io.demo.template.Application类中的greeting方法,并指定该方法的拦截器。
@Override
public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) {
    return new InterceptDeclarer[]{
            InterceptDeclarer.build(MethodMatcher.nameEquals("greeting"), new TemplateInterceptor())
    };
}
  1. 定义针对greeting方法的拦截器,在io.sermant.template.TemplateInterceptorbefore方法中补充System.out.println("Good morning!")逻辑,after方法中补充System.out.println("Good night!")逻辑,before方法和after方法将会在greeting方法执行前后生效。
public class TemplateInterceptor implements Interceptor {
    @Override
    public ExecuteContext before(ExecuteContext context) throws Exception {
        System.out.println("Good morning!");
        return context;
    }

    @Override
    public ExecuteContext after(ExecuteContext context) throws Exception {
        System.out.println("Good night!");
        return context;
    }

    @Override
    public ExecuteContext onThrow(ExecuteContext context) throws Exception {
        return context;
    }
}

注:上述逻辑已在模版代码中实现

# 添加增强声明的SPI配置

开发插件的最后,不要忘记添加增强声明的SPI配置,在工程中template\template-plugin下的资源目录resources中添加META-INF/services目录,并在其中创建名为io.sermant.core.plugin.agent.declarer.PluginDeclarerSPI文件,并向其中添加字节码增强声明类的类名:

io.sermant.template.TemplateDeclarer

# 打包构建

在生成的项目根目录下执行 mvn package,在生成项目的根目录下会生成构建产物目录:

.
├── agent
│   ├── Application.jar
│   ├── common
│   ├── config
│   ├── core
│   ├── god
│   ├── implement
│   ├── pluginPackage
│   │   └── template
│   └── sermant-agent.jar

Application.jar为测试应用的可执行包,其他目录结构参考产品目录说明

注:该模版利用Maven的maven-dependency-plugin:copy插件将Sermant必要核心组件从Maven中心仓拉取到本地构建产物目录中,开发者无需再关心启动Sermant所需的依赖及配置。

maven-dependency-plugin:copy插件使用方式可参考Maven官方文档dmaven-dependency-plugin:copy (opens new window)

在项目根目录执行 cd agent/,在其中执行如下步骤:

  1. 独立运行测试应用,执行如下命令 java -jar Application.jar
$ java -jar Application.jar 
Good afternoon!
  1. 携带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
************省略SpringBoot应用启动日志************
Good morning!
Good afternoon!
Good night!

可以看到,在插件中定义的执行逻辑已被增强到测试应用中,至此你的首个插件就开发成功了,下面开始进行Sermant插件的进阶开发吧。

若需要对Sermant Agent进行Debug调试请参考FAQ的Sermant Agent Debug指南

上次更新: 2024/12/13 02:38:15