使用Javassist在tomcat容器中实现动态Mock

使用场景

在某些复杂场景下,我们需要对运行在tomcat容器中部分功能进行mock(替换其实现),但该部分功能散落在各处,我们希望不修改源代码以非侵入的方式来实现Mock,在这种情况下,我们可以应用Javassist来实现。

使用Javassist来动态Mock

我们可以定义一个ContextListener的实例,在tomcat启动时通过Javassist对源代码进行动态替换,来实现mock的功能。

使用Javassist在tomcat容器中动态替换源码来实现动态Mock:

以下是示例代码片段:

  package test;
  import lombok.extern.log4j.Log4j2;
  import javax.servlet.ServletContextEvent;
  import javax.servlet.ServletContextListener;
  import java.util.HashMap;
  import java.util.Map;
  import org.lightfw.utilx.dynamic.JavassistUtil;
  /**
   */
  @Log4j2
  public class MockListener implements ServletContextListener {

    public void contextInitialized(ServletContextEvent contextEvent) {
        log.info("Context Listener start................");
        //将TestController类的test方法的实现替换为"return 1;"
        JavassitUtil.replaceMethodBody("com.xx.web.controller.TestController", "test", "return 1");
        log.info("Context Listener started");
    }

    public void contextDestroyed(ServletContextEvent sc) {
        log.info("Context Listener stopped");
    }

接下来,在web.xml中添加该Listener就可以了。

<listener>
    <listener-class>test.MockListener</listener-class>
</listener>

Javassist相关代码:

    private static ClassPool classPool;

    static {
        classPool = ClassPool.getDefault();
        classPool.insertClassPath(new ClassClassPath(JavassitUtil.class)); //主要用于web环境
    }

 /**
     * 替换方法体
     *
     * @param className     类名,如:foo.Student
     * @param methodName    方法名
     * @param newMethodBody 新的方法体,如:"System.out.println(\"this method is changed dynamically!\");"
     */
    public static void replaceMethodBody(String className, String methodName, String newMethodBody) {
        try {
            CtClass clazz =classPool.get(className);
            CtMethod method = clazz.getDeclaredMethod(methodName);
            method.setBody(newMethodBody);
            clazz.toClass();
        } catch (NotFoundException | CannotCompileException e) {
            throw new RuntimeException(e);
        }
    }

本例需要使用的工具类可以到以下地址下载:https://github.com/bjo2008cnx/lightfw-util/blob/master/src/main/java/org/lightfw/utilx/dynamic/JavassitUtil.java

发布了31 篇原创文章 · 获赞 12 · 访问量 9万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章