Skip to content

JMeter插件机制

JMeter 插件加载机制

简介

JMeter 插件加载机制主要涉及插件的获取、安装以及如何在 JMeter 中使用这些插件。JMeter 插件加载机制是一个相对简单但功能强大的过程,它允许用户根据需要扩展 JMeter 的功能并满足各种测试需求。

设计模式⼯⼚模式

  • 抽象工厂模式:
    • 提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
    • 抽象工厂模式允许客户端使用抽象的接口来创建一组相关的对象,而不需要知道具体的类名。
    • 它支持增加新的产品族,而不需要修改现有代码,只需要添加新的工厂类即可。 todo 截图

todo 截图

JVM 类加载器

类加载器是用来把类(class)装载进内存的。JVM 规范定义了两种类型的类加载器: 启动类加载器(bootstrap)和用户自定义加载器(user-defned classloader)。 JVM在运行时会产生3个类加载器组成的初始化加载器层次结构,如下图所示:

todo 截图

JMeter 插件化⽅式

  • 提供更强⼤的扩展性和灵活性。
  • 开源,共建 JMeter ⽣态。
  • NewDriver 初始化时,动态加载配置
//ClassFinder needs the classpath
System.setProperty(JAVA _CLASS PATH, initiaclasspath + classpath.tostring());
loader = AccessController.doPrivileged(
        (PrivilegedAction<DynamicClassLoader>)()->
            new DynamicClassLoader(jars.toArray(new URL[jars.size()]))
);

todo 截图

示例代码:

try{
    List<String> listClasses = ClassFinder.findClassesThatExtend(
        JMeterUtils.getSearchPaths(),
        new Class[] {RemoteThreadsLifeCycleListener.class });
    for(String strClassName : listClasses){
        try {
            log.debug("Loading class:{}",strClassName);
            Class<?> commandClass = Class.forName(strClassName);
            if(!Modifier,isAbstract(commandClass.getModifiers())){
                log.debug("Instantiating:{},commandClass);
                RemoteThreadsLifecyclelistener listener = (RemoteThreadsLifeCycleListener) commandclass.getDeclaredconstructor().new
                listeners.add(listener);
            }
        }catch (Exception e){
        log.error("Exception registering {} with implementation: {}", RemoteThreadsLifeCycleListener.class,strClassName,e);
        }
    }
}catch(I0Exception e){
    log,error("Exception finding implementations of {}", RemoteThreadsLifeCyclelistener.class, e);
}
private static final String DOT JAR=".jar";
private static final String DoT CLAss =".class"; 
private static final int DOT CLASS LEN = DOT CLASs.length();
* @param searchPathsOrJars pathnames or jarfiles to search for classes
* @param classNames required parent class(es) or annotations
* @param innerClasses should we include inner classes?
* @param contains classname should contain this string
* @param notContains classname should not contain this string
* @param annotations true if classnames are annotations
* @return List containing discovered classes
* @throws IOException when scanning classes fails
public static List<string> findClassesThatExtend(String[] searchPathsOrJars,
        final Class<?>[]classNames, final boolean innerClasses,
        String contains,String notContains, boolean annotations)
        throws IException {
    if(log.isDebugEnabled()){
        log.debug("findclassesThatExtend with searchPathsOrJars : {}, superclass : {}"+"innerClasses :{}annotations:i contains:i), notcontains: {}".
        Arrays.toString(searchPathsOrJars),
        Arrays.toString(classNames),
        innerClasses,annotations,
        contains, notContains);
    }
    ClassFilter filter;
    if(annotations){
        /unchecked/
        // Should only be called with classes that extend annotations
        final Class<? extends Annotation>[] annoclassNames =(class<?
        extends Annotation>[])classNames;
        filter = new AnnoClassFilter(annoclassNames, innerClasses);
    } else {
        filter = new ExtendsclassFilter(classNames, innerclasses, contains, notContains);
    }
    return findclasses(searchPathsOrJars, filter);
}

JMeter 万物皆插件

在JMeter中,GUI(图形用户界面)元素(如监听器、配置元素、断言、采样器等)经常是通过继承一些抽象类来实现的,以便能够利用这些抽象类提供的共同功能和界面布局。

  • 常见抽象类
    • AbstractSamplerGui:这是所有采样器(Sampler)GUI组件的基类。采样器负责发送请求到服务器并收集响应。
    • AbstractAssertionGui:所有断言(Assertion)GUI组件的基类。断言用于对采样器的响应结果进行验证。
    • AbstractConfigGui:所有配置元素(Config Element)GUI组件的基类。配置元素用于修改采样器或其他组件的行为。
    • AbstractControllerGui:所有控制器(Controller)GUI组件的基类。控制器用于组织和管理采样器或其他组件的执行顺序。
    • AbstractPostProcessorGui:所有后置处理器(Post Processor)GUI组件的基类。后置处理器用于处理采样器返回的响应数据。
    • AbstractPreProcessorGui:所有前置处理器(Pre Processor)GUI组件的基类。前置处理器在采样器执行之前运行,可以对发送到服务器的请求进行修改。
    • AbstractTimerGui:所有定时器(Timer)GUI组件的基类。定时器用于在采样器请求之间添加延迟。
public void logPluginComponents() 
{
    StringBuilder report = new StringBuilder("Plugin Components:\n");
    for(Plugin plugin :getInstalledPlugins()) 
    {
        try {
            Class[] superClasses ={
                Sampler.class,
                Controller.class,
                Timer.class,
                ConfigElement.class,
                PreProcessor.class,
                PostProcessor.class
                Assertion.class,
                SampleListener.class,
                JMeterGUIComponent.class,
                TestBean.class
            };
            String[] searchPaths ={plugin.installedPath};
            List<String> list = ClassFinder.findClassesThatExtend(searchPaths, superClasses);
            report.append(plugin.id).append("\n").append("\"componentClases\":").append(JAONserializer.toJSON(list.toArray()).toString()).append(",\n");
        } catch(Throwable e){
        log.error("Failed to get classes",e);
        }
    }
log.info(report.tostring());
}

JMeter 加载⾮默认⽬录插件

  • 当希望在运行池中动态的加载某个默认目录时可以在测试计划中添加 todo 截图

总结

  • 简介
  • 设计模式⼯⼚模式
  • JVM 类加载器
  • JMeter 插件化⽅式
  • JMeter 万物皆插件