使用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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章