8. jvm-sandbox之服务接口扫描2

服务接口扫描2

一、概述

之前写过一版利用jvm-sandbox扫描服务接口的文章,最近重新看了一下源码中的样例,发现了一个新接口Progress,利用它可以监控到渲染的过程。它可以让服务接口信息的获取变得更加简洁便利。

二、Progress接口代码

    /**
     * 进度报告
     * <p>
     * 观察类是需要对类进行增强,有时候需要对大量的类进行渲染,耗时比较长。
     * 通过这样的报告方式可以让外部感知到当前渲染的进度。
     * 在渲染完成之前,事件是不会触发给到{@link EventListener}的
     * </p>
     */
    interface Progress {

        /**
         * 进度开始
         *
         * @param total 总共需要渲染类的总数
         */
        void begin(int total);

        /**
         * 进度报告(成功)
         *
         * @param clazz 当前进行行变的类
         * @param index 当前形变类的序号,从0开始
         */
        void progressOnSuccess(Class<?> clazz, int index);

        /**
         * 进度报告(失败)
         *
         * @param clazz 当前进行行变的类
         * @param index 当前形变类的序号,从0开始
         * @param cause 失败异常
         */
        void progressOnFailed(Class<?> clazz, int index, Throwable cause);

        /**
         * 进度结束
         * <p>如果是add方法,则影响的数量是递增;</p>
         * <p>如果是remove方法,则影响的数量是递减;</p>
         * <p>当彻remove完成之后,cCnt = mCnt = 0;</p>
         *
         * @param cCnt 影响类总数
         * @param mCnt 影响方法总数
         */
        void finish(int cCnt, int mCnt);

    }

三、获取方法

第一步 实现Progress 接口


import com.alibaba.fastjson.JSONObject;
import com.alibaba.jvm.sandbox.api.resource.ModuleEventWatcher;
import com.custom.util.HttpUtil;
import com.custom.util.InstanceUtils;
import org.slf4j.Logger;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class ControllerProcessInfo implements ModuleEventWatcher.Progress {

    Logger lifeCLogger;
    public String serviceName;

    public List<InterfaceInfo> interfaceInfoList;

    public ControllerProcessInfo(Logger lifeCLogger,String serviceName) {
        this.lifeCLogger = lifeCLogger;
        this.interfaceInfoList=new ArrayList<>();
        this.serviceName=serviceName;
    }

    public List<InterfaceInfo> getInterfaceInfoList(){
        return this.interfaceInfoList;
    }

    @Override
    public void begin(int total) {
        lifeCLogger.debug("渲染总个数:{}", total);
    }

    @Override
    public void progressOnSuccess(Class<?> clazz, int index) {
        lifeCLogger.debug("{} 渲染成功:{}", index, clazz.getName());
        InterfaceInfo interfaceInfo=new InterfaceInfo();

//**通过反射获取注解的value。这里获取RequestMapping注解的value**

        ClassMappingInfo classMappingInfo=new ClassMappingInfo();
        classMappingInfo.setClassName(clazz.getName());

        String basePath = "";
        Annotation[] annotations = clazz.getAnnotations();
        for (Annotation annotation : annotations) {
            if (annotation.toString().contains("RequestMapping")) {//直接使用getAnnotation(RequestMapping.class)获取不到annotation.     annotation.getClass().getName()的值是com.sun.proxy.$Proxy80
                String[] s = (String[]) InstanceUtils.doMethodByName("value", annotation);
                basePath = s[0];
                classMappingInfo.setBasePath(basePath);
            }
        }
        interfaceInfo.setClassInfo(classMappingInfo);


        List<MethodMappingInfo> methodMappingInfoList=new ArrayList<>();
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            Annotation[] annotations_m = method.getAnnotations();
            for (Annotation annotation_m : annotations_m) {
                //lifeCLogger.debug("annotation_m:{}", annotation_m.toString());//annotation_m:@org.springframework.web.bind.annotation.RequestMapping(headers=[], path=[], method=[], produces=[], name=, params=[], value=[/insertUser], consumes=[])
                if (annotation_m.toString().contains("org.springframework.web.bind.annotation") && annotation_m.toString().contains("Mapping") ) {
                    //获取注解值
                    String[] s_m = (String[]) InstanceUtils.doMethodByName("value", annotation_m);
                    String path = s_m[0];

                    MethodMappingInfo methodMappingInfo=new MethodMappingInfo();
                    methodMappingInfo.setMethodName(method.getName());
                    methodMappingInfo.setAccessPath(path);
                    methodMappingInfo.setDetail(method.toString());
                    methodMappingInfo.setAnnotationInfo(annotation_m.toString());

                    methodMappingInfoList.add(methodMappingInfo);
                }
            }
        }
        interfaceInfo.setMethodInfo(methodMappingInfoList);
        interfaceInfoList.add(interfaceInfo);
    }

    @Override
    public void progressOnFailed(Class<?> clazz, int index, Throwable cause) {
        lifeCLogger.debug("{} 渲染失败:{}", index, clazz.getName());
    }

    @Override
    public void finish(int cCnt, int mCnt) {
        lifeCLogger.debug("渲染完成:类个数={} 方法个数={}", cCnt, mCnt);
        
    }
}

第二步 将实现类的实例,按下图方法设置一下即可

posted @ 2022-12-06 17:05  月色深潭  阅读(176)  评论(0)    收藏  举报