Java Agent字节码增强技术实现链路追踪[通俗易懂]

Java Agent字节码增强技术实现链路追踪[通俗易懂]javaagent

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

说明:使用bytebuddy框架来实现 RestTemplate链路追踪,并且将日志id追加到头部,借鉴 skywalking 中增强技术;直接上代码。

maven依赖


<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <byte.buddy.version>1.9.6</byte.buddy.version>
        <lombok.version>1.18.22</lombok.version>
        <log4.version>1.2.17</log4.version>
        <log4.api.version>1.7.21</log4.api.version>
        <spring.web.version>5.2.8.RELEASE</spring.web.version>
        <dubbo.version>2.7.0</dubbo.version>
        <javax.version>4.0.1</javax.version>
    </properties>

<dependency>
            <groupId>net.bytebuddy</groupId>
            <artifactId>byte-buddy</artifactId>
            <version>${byte.buddy.version}</version>
        </dependency>

        <dependency>
            <groupId>net.bytebuddy</groupId>
            <artifactId>byte-buddy-agent</artifactId>
            <version>${byte.buddy.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.web.version}</version>
            <scope>provided</scope>
        </dependency>

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.web.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
            <version>${dubbo.version}</version>
            <scope>provided</scope>
        </dependency>
        
<dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${javax.version}</version>
            <scope>provided</scope>
        </dependency>

Jetbrains全家桶1年46,售后保障稳定

1. 入口类

public class TraceAgent
{ 
   

    public static void premain(String args, Instrumentation instrumentation) { 
   
    	//将插件从文件中读取出来
        PluginFinder pluginFinder = new PluginFinder(new PluginBootstrap().loadPlugins());
        //创建一个代理增强对象
        new AgentBuilder.Default()
        //通过自定义实现的类去拦截指定的对象
            .type(pluginFinder.buildMatch())  //拦截指定的类
            .transform(new Transformer(pluginFinder))
            .installOn(instrumentation);
    }

    public static class Transformer implements AgentBuilder.Transformer { 
   
       //插件持有器
        private final PluginFinder pluginFinder;

        public Transformer(PluginFinder pluginFinder) { 
   
            this.pluginFinder = pluginFinder;
        }

        @Override
        public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader,
                                                JavaModule javaModule) { 
   
                                                //获取到插件,构建一个动态插件器
            List<ClassEnhancePluginDefine> classEnhancePluginDefines = pluginFinder.find(typeDescription);
            if (classEnhancePluginDefines.size() > 0) { 
   
            //判断当前插件是否符合当前的拦截对象
                DynamicType.Builder<?> newBuilder = builder;
                //调用插件的define方法去获取到动态类型构造器,就是去返回需要匹配方法的增强方法
                for (ClassEnhancePluginDefine define : classEnhancePluginDefines) { 
   
                    DynamicType.Builder<?> possibleNewBuilder = define.define(builder, classLoader);
                    if (possibleNewBuilder != null) { 
   
                        newBuilder = possibleNewBuilder;
                    }
                }
                return newBuilder;
            }
            return builder;
        }
    }

}

2. 插件读取器

public class PluginBootstrap { 
   

    /** PLUGINS */
    private static final String PLUGINS = "agent-plugin.def";

  	//主要是将文件中的插件读取出来,然后通过名称构造出来
    public List<ClassEnhancePluginDefine> loadPlugins() { 
   
        ClassPathResource classPathResource = new ClassPathResource(PLUGINS);
        List<ClassEnhancePluginDefine> enhancePluginDefines = new ArrayList<>();
        try { 
   
            if (!classPathResource.exists()) { 
   
                return enhancePluginDefines;
            }
            
            InputStreamReader streamReader = new InputStreamReader(classPathResource.getInputStream());
            BufferedReader reader = new BufferedReader(streamReader);
            String tempString;
            while ((tempString = reader.readLine()) != null) { 
   
                if (tempString.trim().length() == 0 || tempString.startsWith("#")) { 
   
                    continue;
                }
                if (StringUtils.isEmpty(tempString)) { 
   
                    continue;
                }

                String[] pluginDefine = tempString.split("=");
                if (pluginDefine.length != 2) { 
   
                    continue;
                }
                log.debug("读取到插件类:{}", pluginDefine[1]);
                ClassEnhancePluginDefine classEnhancePluginDefine = (ClassEnhancePluginDefine) Class.forName(pluginDefine[1],
                                                                                                             true,
                                                                                                             this.getClass().getClassLoader())
                    .newInstance();
                enhancePluginDefines.add(classEnhancePluginDefine);
            }
        } catch (Exception e) { 
   
            log.error("读取插件配置异常:", e);
        }
        return enhancePluginDefines;
    }
}

3. agent-plugin.def文件定义

spring-resttemplate=com.xxx.agent.interceptor.resttemplate.sync.RestTemplateInstrumentation
dubbo=com.xxx.agent.interceptor.doubbo.DubboInstrumentation
httpServlet=com.xxx.agent.interceptor.httpservlet.HttpServletInstrumentation

4. 插件持有器

public class PluginFinder { 
   
    private final Map<String, LinkedList<ClassEnhancePluginDefine>> nameMatchDefine = new HashMap<>();


    //将读取出来的插件传入到 PluginFinder 持有器中
    public PluginFinder(List<ClassEnhancePluginDefine> classEnhancePluginDefines) { 
   
        //遍历插件的名称,并且添加到名字匹配器当中
        classEnhancePluginDefines.forEach(classEnhancePluginDefine -> { 
   
            //调用插件的实现方法,将需要增强的对象设置到map当中,value就是多个插件List
            String enhanceClass = classEnhancePluginDefine.enhanceClass();
            LinkedList<ClassEnhancePluginDefine> enhancePluginDefines = nameMatchDefine.computeIfAbsent(enhanceClass,
                                                                                                        k -> new LinkedList<>());
            enhancePluginDefines.add(classEnhancePluginDefine);
        });
    }
	//通过传入的 typeDescription 对象来判断是否是指定要增强的类,并且返回插件
    public List<ClassEnhancePluginDefine> find(TypeDescription typeDescription) { 
   
        List<ClassEnhancePluginDefine> matchedPlugins = new LinkedList<ClassEnhancePluginDefine>();
        String typeName = typeDescription.getTypeName();
        if (nameMatchDefine.containsKey(typeName)) { 
   
            matchedPlugins.addAll(nameMatchDefine.get(typeName));
        }
        return matchedPlugins;
    }

    //构建一个匹配器
    public ElementMatcher<? super TypeDescription> buildMatch() { 
   
        ElementMatcher.Junction elementMatcher = new AbstractJunction<NamedElement>() { 
   
            @Override
            //判断class名称是否是自己需要增强,在初始化的时候就把插件需要增强的类设置进去了
            public boolean matches(NamedElement namedElement) { 
   
                return nameMatchDefine.containsKey(namedElement.getActualName());
            }
        };
        //判断需要创建的对象是不是一个接口
        elementMatcher = elementMatcher.and(not(isInterface()));
        for (String matchClass : nameMatchDefine.keySet()) { 
   
            elementMatcher = elementMatcher.or(nameStartsWithIgnoreCase(matchClass));
        }
        //然后返回属性匹配器
        return new ProtectiveShieldMatcher<>(elementMatcher);
    }

}
public class ProtectiveShieldMatcher<T> extends ElementMatcher.Junction.AbstractBase<T> { 
   

    /** Element matcher */
    private final ElementMatcher<? super T> elementMatcher;

    /** * Protective shield matcher * * @param elementMatcher element matcher * @since 1.0.0 */
    public ProtectiveShieldMatcher(ElementMatcher<? super T> elementMatcher) { 
   
        this.elementMatcher = elementMatcher;
    }

    /** * Matches * * @param target target * @return the boolean * @since 1.0.0 */
    @Override
    public boolean matches(T target) { 
   
        try { 
   
            return this.elementMatcher.matches(target);
        } catch (Throwable t) { 
   
            log.warn("匹配增强类失败:{}", t.getMessage());
            return false;
        }
    }
}
public abstract class AbstractJunction<S> implements ElementMatcher.Junction<S> { 
   

    /** * And * * @param <U> parameter * @param elementMatcher element matcher * @return the junction * @since 1.0.0 */
    @Override
    public <U extends S> Junction<U> and(ElementMatcher<? super U> elementMatcher) { 
   
        return new Conjunction<>(this, elementMatcher);
    }

    /** * Or * * @param <U> parameter * @param elementMatcher element matcher * @return the junction * @since 1.0.0 */
    @Override
    public <U extends S> Junction<U> or(ElementMatcher<? super U> elementMatcher) { 
   
        return new Disjunction<>(this, elementMatcher);
    }
}

5. 插件定义的顶级接口类

public interface ClassEnhancePluginDefine { 
   

    /** * 需要增强的类 * * @return the string * @since 1.0.0 */
    String enhanceClass();

    /** * 获取到定义方法 * * @return the dynamic type . builder * @since 1.0.0 */
    DynamicType.Builder<?> define(DynamicType.Builder<?> newBuilder,
                                  ClassLoader classLoader);

    /** * 获取到需要增强的具体方法 * * @return the list * @since 1.0.0 */
    InstanceMethodsInterceptPoint[] enhanceInstance();

}

6. 抽象插件类

public abstract class AbstractClassEnhancePluginDefine implements ClassEnhancePluginDefine { 
   

    @Override
    public DynamicType.Builder<?> define(DynamicType.Builder<?> newBuilder, ClassLoader classLoader) { 
   
        //获取到需要拦截的方法
        InstanceMethodsInterceptPoint[] instanceMethodsInterceptPoints = this.enhanceInstance();
        if (instanceMethodsInterceptPoints.length <= 0) { 
   
            return newBuilder;
        }
        //遍历需要拦截点位
        for (InstanceMethodsInterceptPoint instanceMethodsInterceptPoint : instanceMethodsInterceptPoints) { 
   
            //需要使用的拦截器
            Class<?> interceptor = instanceMethodsInterceptPoint.getMethodsInterceptor();
            //获取到需要拦截的方法匹配器
            ElementMatcher.Junction<MethodDescription> junction
                = not(isStatic()).and(instanceMethodsInterceptPoint.getMethodsMatcher());
            //将需要拦截的方法以及执行的拦截器挂载到builder上
            newBuilder = newBuilder
                .method(junction)
                .intercept(MethodDelegation
                               .withDefaultConfiguration()
                               .to(new InstMethodsInter(interceptor)));
        }
        return newBuilder;
    }
}

7. 增强方法的顶级接口

public interface InstanceMethodsInterceptPoint { 
   

    /** * 方法匹配器 * * @return the methods matcher * @since 1.0.0 */
    ElementMatcher<MethodDescription> getMethodsMatcher();

    /** * 方法拦截器 * * @return the methods interceptor * @since 1.0.0 */
    Class<?> getMethodsInterceptor();

    /** * 是否覆盖参数,暂未实现 * * @return the boolean * @since 1.0.0 */
    boolean isOverrideArgs();
}

8. 环绕方法的拦截器

public interface InstanceMethodsAroundInterceptor { 
   

    /** * Before method * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @throws Throwable throwable * @since 1.0.0 */
    void beforeMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes) throws Throwable;

    /** * After method * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @param result result * @return the object * @throws Throwable throwable * @since 1.0.0 */
    Object afterMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object result) throws Throwable;

    /** * Handle method exception * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @param t t * @since 1.0.0 */
    void handleMethodException(Object objInst, Method method, Object[] allArguments,
                               Class<?>[] argumentsTypes, Throwable t);
}

9. 方法执行的包装方法

public class InstMethodsInter { 
   

    /** Interceptor */
    private InstanceMethodsAroundInterceptor interceptor;

    /** * Inst methods inter * * @param interceptorName interceptor name * @since 1.0.0 */
    public InstMethodsInter(@NonNull Class<?> interceptorName) { 
   
        try { 
   
            this.interceptor = (InstanceMethodsAroundInterceptor) interceptorName.newInstance();
        } catch (Exception e) { 
   
            e.printStackTrace();
        }
    }

    /** * Intercept * * @param obj obj * @param allArguments all arguments * @param method method * @param callable callable * @return the object * @since 1.0.0 */
    @RuntimeType
    public Object intercept(@This Object obj,
                            @AllArguments Object[] allArguments,
                            @Origin Method method,
                            @SuperCall Callable<?> callable) { 
   
        Object result = null;
        try { 
   
            interceptor.beforeMethod(obj, method, allArguments, method.getParameterTypes());
        } catch (Throwable throwable) { 
   
            log.error("前置增强方法执行异常:", throwable);
        }
        try { 
   
        	//真正方法的执行
            result = callable.call();
        } catch (Throwable t) { 
   
            interceptor.handleMethodException(obj, method, allArguments, method.getParameterTypes(), t);
        } finally { 
   
            try { 
   
                result = interceptor.afterMethod(obj, method, allArguments, method.getParameterTypes(), result);
            } catch (Throwable t) { 
   
                log.error("后置增强方法执行异常:", t);
            }
        }
        return result;
    }

}

10. 实现的插件类

RestTemplate 增强类

public class RestTemplateInstrumentation extends AbstractClassEnhancePluginDefine { 
   

    /** 需要增强的类*/
    private static final String ENHANCE_CLASS = "org.springframework.web.client.RestTemplate";

    /** 需要增强的方法*/
    private static final String DO_EXECUTE_METHOD_NAME = "doExecute";

    /** 对应增强方法执行的类*/
    private static final Class<?> DO_EXECUTE_INTERCEPTOR = RestExecuteInterceptor.class;

    /** 需要增强的方法*/
    private static final String HANDLE_REQUEST_METHOD_NAME = "handleResponse";

    /** 对应增强方法执行的类*/
    private static final Class<?> HAND_REQUEST_INTERCEPTOR = RestResponseInterceptor.class;

    /** 需要增强的方法 */
    private static final String CREATE_REQUEST_METHOD_NAME = "createRequest";

    /** 对应增强方法执行的类*/
    private static final Class<?> CREATE_REQUEST_INTERCEPTOR = RestRequestInterceptor.class;

    /** * Enhance class * * @return the string * @since 1.0.0 */
    @Override
    public String enhanceClass() { 
   
        return ENHANCE_CLASS;
    }

    /** * Enhance instance * * @return the instance methods intercept point [ ] * @since 1.0.0 */
    @Override
    public InstanceMethodsInterceptPoint[] enhanceInstance() { 
   
        return new InstanceMethodsInterceptPoint[] { 
   
            new InstanceMethodsInterceptPoint() { 
   
                @Override
                public ElementMatcher<MethodDescription> getMethodsMatcher() { 
   
                    return named(CREATE_REQUEST_METHOD_NAME);
                }

                @Override
                public Class<?> getMethodsInterceptor() { 
   
                    return CREATE_REQUEST_INTERCEPTOR;
                }

                @Override
                public boolean isOverrideArgs() { 
   
                    return false;
                }
            },
            new InstanceMethodsInterceptPoint() { 
   
                @Override
                public ElementMatcher<MethodDescription> getMethodsMatcher() { 
   
                    return named(DO_EXECUTE_METHOD_NAME);
                }

                @Override
                public Class<?> getMethodsInterceptor() { 
   
                    return DO_EXECUTE_INTERCEPTOR;
                }

                @Override
                public boolean isOverrideArgs() { 
   
                    return false;
                }
            },
            new InstanceMethodsInterceptPoint() { 
   
                @Override
                public ElementMatcher<MethodDescription> getMethodsMatcher() { 
   
                    return named(HANDLE_REQUEST_METHOD_NAME);
                }

                @Override
                public Class<?> getMethodsInterceptor() { 
   
                    return HAND_REQUEST_INTERCEPTOR;
                }

                @Override
                public boolean isOverrideArgs() { 
   
                    return false;
                }
            }
        };
    }
}
1. excute() 方法
public class RestExecuteInterceptor implements InstanceMethodsAroundInterceptor { 
   

    @Override
    public void beforeMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes) throws Throwable { 
   

    }

    @Override
    public Object afterMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object result) throws Throwable { 
   
        return result;
    }

    @Override
    public void handleMethodException(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) { 
   
        //调用异常之后打印调用链路
        RuntimeContextManager.printTraceLog();
    }
}
2. createRequest() 方法
public class RestRequestInterceptor implements InstanceMethodsAroundInterceptor { 
   

    @Override
    public void beforeMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes) throws Throwable { 
   

    }

    @Override
    public Object afterMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object result) throws Throwable { 
   
        ClientHttpRequest clientHttpRequest = (ClientHttpRequest) result;
        if (clientHttpRequest instanceof AbstractClientHttpRequest) { 
   
            AbstractClientHttpRequest httpRequest = (AbstractClientHttpRequest) clientHttpRequest;
            //将traceId追加到header头当中
            RuntimeContextManager.CarrierItem item = RuntimeContextManager.get();
            while (item.hasNext()) { 
   
                item = item.next();
                httpRequest.getHeaders().add(ConstName.HEAD_KEY, item.getHeadValue());
            }
        }
        return result;
    }

    @Override
    public void handleMethodException(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) { 
   
        RuntimeContextManager.printTraceLog();
    }
}

3. handleResponse() 方法
public class RestResponseInterceptor implements InstanceMethodsAroundInterceptor { 
   

    /** * Before method * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @throws Throwable throwable * @since 1.0.0 */
    @Override
    public void beforeMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes) throws Throwable { 
   

    }

    /** * After method * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @param result result * @return the object * @throws Throwable throwable * @since 1.0.0 */
    @Override
    public Object afterMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object result) throws Throwable { 
   
        ClientHttpResponse clientHttpResponse = (ClientHttpResponse) allArguments[1];
        List<String> traceList = clientHttpResponse.getHeaders().get(ConstName.HEAD_KEY);
        if (!CollectionUtils.isEmpty(traceList)) { 
   
            RuntimeContextManager.remove();
            //将trace放到 manager当中存储
            traceList.forEach(trace -> { 
   
                RuntimeContextManager.add(RuntimeContextManager.CarrierItem.item(trace, trace));
            });
        }
        return result;
    }

    /** * Handle method exception * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @param t t * @since 1.0.0 */
    @Override
    public void handleMethodException(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) { 
   
        RuntimeContextManager.printTraceLog();
    }
}

servlet 增强类

public class HttpServletInstrumentation extends AbstractClassEnhancePluginDefine { 
   

    private static final String ENHANCE_CLASS = "org.springframework.web.servlet.DispatcherServlet";

    private static final String DO_FILTER_METHOD = "service";

    private static final Class<HttpServletInterceptor> DO_FILTER_INTERCEPTOR = HttpServletInterceptor.class;


    /** * Enhance class * * @return the string * @since 1.0.0 */
    @Override
    public String enhanceClass() { 
   
        return ENHANCE_CLASS;
    }

    /** * Enhance instance * * @return the instance methods intercept point [ ] * @since 1.0.0 */
    @Override
    public InstanceMethodsInterceptPoint[] enhanceInstance() { 
   
        return new InstanceMethodsInterceptPoint[] { 
   
            new InstanceMethodsInterceptPoint() { 
   
                @Override
                public ElementMatcher<MethodDescription> getMethodsMatcher() { 
   
                    //拦截对应的方法,并且是public方法
                    return named(DO_FILTER_METHOD).and(isPublic());
                }

                @Override
                public Class<?> getMethodsInterceptor() { 
   
                    return DO_FILTER_INTERCEPTOR;
                }

                @Override
                public boolean isOverrideArgs() { 
   
                    return false;
                }
            }
        };
    }
}
1. service() 方法
public class HttpServletInterceptor implements InstanceMethodsAroundInterceptor { 
   

    /** * Before method * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @throws Throwable throwable * @since 1.0.0 */
    @Override
    public void beforeMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes) throws Throwable { 
   
        HttpServletRequest httpRequest = (HttpServletRequest) allArguments[0];
        Enumeration<String> headers = httpRequest.getHeaders(ConstName.HEAD_KEY);
        //将请求头的数据读取出来后清除掉头部数据
        if (headers.hasMoreElements()) { 
   
            String nextElement = headers.nextElement();
            RuntimeContextManager.CarrierItem carrierItem
                = RuntimeContextManager.CarrierItem.item(nextElement, nextElement);
            RuntimeContextManager.add(carrierItem);
        }
        RuntimeContextManager.CarrierItem next = RuntimeContextManager.CarrierItem.item(System.getProperty(ConstName.CONFIG_APP_NAME),
                                                                                        System.getProperty(ConstName.CONFIG_APP_NAME));
        RuntimeContextManager.add(next);
        httpRequest.removeAttribute(ConstName.HEAD_KEY);
    }

    /** * After method * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @param result result * @return the object * @throws Throwable throwable * @since 1.0.0 */
    @Override
    public Object afterMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object result) throws Throwable { 
   
        HttpServletResponse httpServletResponse = (HttpServletResponse) allArguments[1];
        RuntimeContextManager.addResponseHeaders(httpServletResponse);
        RuntimeContextManager.printTraceLog();
        RuntimeContextManager.remove();
        return result;
    }

    /** * Handle method exception * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @param t t * @since 1.0.0 */
    @Override
    public void handleMethodException(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) { 
   
        RuntimeContextManager.printTraceLog();
        RuntimeContextManager.remove();
    }

}

dubbo 增强类

public class DubboInstrumentation extends AbstractClassEnhancePluginDefine { 
   

    private static final String ENHANCE_CLASS = "org.apache.dubbo.monitor.support.MonitorFilter";

    private static final Class<DubboInterceptor> INTERCEPT_CLASS = DubboInterceptor.class;

    /** DO_EXECUTE_METHOD_NAME */
    private static final String INVOKE_METHOD_NAME = "invoke";

    @Override
    public String enhanceClass() { 
   
        return ENHANCE_CLASS;
    }

    @Override
    public InstanceMethodsInterceptPoint[] enhanceInstance() { 
   
        return new InstanceMethodsInterceptPoint[] { 
   
            new InstanceMethodsInterceptPoint() { 
   
                @Override
                public ElementMatcher<MethodDescription> getMethodsMatcher() { 
   
                    return named(INVOKE_METHOD_NAME);
                }

                @Override
                public Class<DubboInterceptor> getMethodsInterceptor() { 
   
                    return INTERCEPT_CLASS;
                }

                @Override
                public boolean isOverrideArgs() { 
   
                    return false;
                }
            }
        };
    }
}
1. invoke() 方法
public class DubboInterceptor implements InstanceMethodsAroundInterceptor { 
   

    /** * Before method * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @throws Throwable throwable * @since y.y.y */
    @Override
    public void beforeMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes) throws Throwable { 
   
        Invoker invoker = (Invoker) allArguments[0];
        Invocation invocation = (Invocation) allArguments[1];
        RpcContext rpcContext = RpcContext.getContext();
        boolean isConsumer = rpcContext.isConsumerSide();
        URL requestURL = invoker.getUrl();
        if (isConsumer) { 
   
            //添加一次当前服务的名称
            RuntimeContextManager.add(RuntimeContextManager.CarrierItem.item(System.getProperty(ConstName.CONFIG_APP_NAME),
                                                                             System.getProperty(ConstName.CONFIG_APP_NAME)));
            //判断如果是消费者,将数据写入请求头
            String traceStr = RuntimeContextManager.getTraceStr();
            rpcContext.getAttachments().put(ConstName.HEAD_KEY, traceStr);
        } else { 
   
            //如果是提供者
            String traceStr = rpcContext.getAttachments().get(ConstName.HEAD_KEY);
            RuntimeContextManager.addTraceForStr(traceStr);
        }
    }

    /** * After method * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @param result result * @return the object * @throws Throwable throwable * @since y.y.y */
    @Override
    public Object afterMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object result) throws Throwable { 
   
        return null;
    }

    /** * Handle method exception * * @param objInst obj inst * @param method method * @param allArguments all arguments * @param argumentsTypes arguments types * @param t t * @since y.y.y */
    @Override
    public void handleMethodException(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) { 
   

    }

    /** * Generate operation name * * @param requestURL request url * @param invocation invocation * @return the string * @since y.y.y */
    private String generateOperationName(URL requestURL, Invocation invocation) { 
   
        StringBuilder operationName = new StringBuilder();
        String groupStr = requestURL.getParameter(Constants.GROUP_KEY);
        groupStr = StringUtils.isEmpty(groupStr) ? "" : groupStr + "/";
        operationName.append(groupStr);
        operationName.append(requestURL.getPath());
        operationName.append("." + invocation.getMethodName() + "(");
        for (Class<?> classes : invocation.getParameterTypes()) { 
   
            operationName.append(classes.getSimpleName() + ",");
        }
        if (invocation.getParameterTypes().length > 0) { 
   
            operationName.delete(operationName.length() - 1, operationName.length());
        }
        operationName.append(")");
        return operationName.toString();
    }

    /** * Generate request url * * @param url url * @param invocation invocation * @return the string * @since y.y.y */
    private String generateRequestURL(URL url, Invocation invocation) { 
   
        StringBuilder requestURL = new StringBuilder();
        requestURL.append(url.getProtocol() + "://");
        requestURL.append(url.getHost());
        requestURL.append(":" + url.getPort() + "/");
        requestURL.append(generateOperationName(url, invocation));
        return requestURL.toString();
    }
}

11. 上下文持有器

public class RuntimeContextManager { 
   

    private final static ThreadLocal<CarrierItem> RUNTIME_CARRIER = new ThreadLocal<>();

    public static CarrierItem get() { 
   
        CarrierItem carrierItem = RUNTIME_CARRIER.get();
        if (carrierItem == null) { 
   
            carrierItem = new CarrierItem(Thread.currentThread().getName(), System.currentTimeMillis()+"", null);
            RUNTIME_CARRIER.set(carrierItem);
        }
        return carrierItem;
    }

    public static void remove() { 
   
        RUNTIME_CARRIER.remove();
    }

    public static void add(CarrierItem next) { 
   
        CarrierItem item = get();
        while (item.hasNext()) { 
   
            item = item.next();
        }
        //如果尾部的服务名跟添加时的一样,就不需要再添加
        String headValue = item.getHeadValue();
        if (headValue.equalsIgnoreCase(next.headValue)) { 
   
            return;
        }
        item.setNext(next);
    }

    public static void addRequestHeaders(ClientHttpRequest clientHttpRequest) { 
   
        CarrierItem carrierItem = get();
        clientHttpRequest.getHeaders().remove(ConstName.HEAD_KEY);
        while (carrierItem.hasNext()) { 
   
            carrierItem = carrierItem.next;
            clientHttpRequest.getHeaders().add(ConstName.HEAD_KEY, carrierItem.headValue);
        }
    }

    public static void addResponseHeaders(ServletResponse servletResponse) { 
   
        CarrierItem carrierItem = get();
        if (servletResponse instanceof HttpServletResponse) { 
   
            while (carrierItem.hasNext()) { 
   
                carrierItem = carrierItem.next;
                ((HttpServletResponse) servletResponse).addHeader(ConstName.HEAD_KEY, carrierItem.headValue);
            }
        }
    }

    public static void printTraceLog() { 
   
        String s = getTraceStr();
        if (s == null) { 
   
            return;
        }
        log.info("服务调用路径:{}", s);
    }

    public static String getTraceStr() { 
   
        CarrierItem carrierItem = get();
        List<String> items = new ArrayList<>();
        while (carrierItem.hasNext()) { 
   
            carrierItem = carrierItem.next;
            items.add(carrierItem.headValue);
        }
        if (CollectionUtils.isEmpty(items)) { 
   
            return null;
        }
        return items.stream().map(String::valueOf).collect(Collectors.joining(ConstName.DELIMITER));
    }

    public static void addTraceForStr(String traceStr) { 
   
        if (StringUtils.isEmpty(traceStr)) { 
   
            return;
        }
        String[] trace = StringUtils.split(traceStr, ConstName.DELIMITER);
        Arrays.stream(trace).forEach(str -> { 
   
            add(CarrierItem.item(str, str));
        });
    }


    public static class CarrierItem implements Iterator<CarrierItem> { 
   

        private String headKey;

        private String headValue;

        private CarrierItem next;

        public CarrierItem() { 
   
        }

        public CarrierItem(String headKey, String headValue) { 
   
            this(headKey, headValue, null);
        }

        public CarrierItem(String headKey, String headValue, CarrierItem next) { 
   
            this.headKey = headKey;
            this.headValue = headValue;
            this.next = next;
        }

        public static CarrierItem item(String headKey, String headValue) { 
   
            return new CarrierItem(headKey, headValue);
        }

        @Override
        public boolean hasNext() { 
   
            return next != null;
        }

        @Override
        public CarrierItem next() { 
   
            return next;
        }

        @Override
        public void remove() { 
   

        }

        public String getHeadKey() { 
   
            return headKey;
        }

        public void setHeadKey(String headKey) { 
   
            this.headKey = headKey;
        }

        public String getHeadValue() { 
   
            return headValue;
        }

        public void setHeadValue(String headValue) { 
   
            this.headValue = headValue;
        }

        public CarrierItem getNext() { 
   
            return next;
        }

        public void setNext(CarrierItem next) { 
   
            this.next = next;
        }
    }
}

public class ConstName { 
   

    /** CONFIG_APP_NAME */
    public static final String CONFIG_APP_NAME = "APP_NAME";

    /** HEAD_KEY */
    public static final String HEAD_KEY = "Trace";

    /** 分隔符 */
    public static final String DELIMITER = "--->";

}

由于公司封装的框架原因,导致restTemplate增强会有问题,所以一在拦截handResponse()会导致提前返回对象;但是大体框架没有问题,都是根据skywalking的源码进行修改,各位看官根据具体的业务可以进行实现;如果有什么错误的地方,还请各位大佬指教

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/213943.html原文链接:https://javaforall.net

(0)
上一篇 2025年7月16日 下午10:01
下一篇 2025年7月16日 下午10:43


相关推荐

  • android游戏开发引擎_engine引擎

    android游戏开发引擎_engine引擎一起学习,加群86896009

    2025年12月1日
    6
  • harmonyos系统与安卓区别(uAndroid)

    目录一、前言二、HarmonyOS与Android的对比2.1HarmonyOS并不是Android的替代品2.2系统定位2.3内核对比2.4运行速度三、方舟编译器一、前言这段时间我在寻思这学习一下鸿蒙,第一是因为在着手做一个自己的开源项目,技术选型的时候想到了鸿蒙;第二是我个人非常看好鸿蒙系统的未来,清除明白华为和一些民族企业担负的责任和国人的期待,虽然带着一些民族感情;鸿蒙刚发布的时候自己是非常激动的,但是后来项目太忙一直没有认真的去了解过,这次打算花一部

    2022年4月13日
    161
  • 常用quartz表达式

    常用quartz表达式0012 每天中午 12 点触发 nbsp 01510 每天上午 10 15 触发 nbsp 01510 每天上午 10 15 触发 nbsp 01510 每天上午 10 15 触发 nbsp 01510 2005 2005 年的每天上午 10 15 触发 nbsp 0 14 在每天下午 2 点到下午 2 59 期间的每 1 分钟触发 nbsp 0

    2026年3月19日
    2
  • Docker与自动化部署

    Docker与自动化部署Docker 安装与基本使用虚拟机系统 centOS7miniD 的应用场景 1 简化配置 同一 Docker 的配置可以在不同环境中使用 降低了硬件要求和应用环境之间的耦合度 nbsp 2 代码的流水线管理 代码从开发者的假期到最终在生产环境上的部署 需要经过很多的中间环境 而每一个中间环境都有自己微小的蛤贝 Docker 给应用提供一个从开发到上线均一致的环境 让代码的流水线变得简单 nbsp 3 提高开发效

    2026年3月18日
    2
  • 解决无法删除文件夹的情况:文件夹正在使用,操作无法完成,因为其中的文件,或文件夹已在另一个程序中打开…

    解决无法删除文件夹的情况:文件夹正在使用,操作无法完成,因为其中的文件,或文件夹已在另一个程序中打开…在删除文件夹的时候 可能会遇到文件夹正在使用 操作无法完成 因为其中的文件 或文件夹已在另一个程序中打开 请关闭该文件夹或或文件 然后重试 这类无法关闭删除文件夹的情况 如下图所示 解决这个的关键是 找到是哪个程序在使用该文件夹 把这个程序关闭掉就行了 但有时说实在的并不好找 下面来介绍一个方便的找到这些程序的方法 首先按 ctrl shitf esc 快捷键 打开任务管理器 然后

    2026年3月16日
    2
  • vs 安装包_vs离线安装包

    vs 安装包_vs离线安装包VS安装包注册com组件VS安装包注册com组件1.把你的com组件加入到打包程序。 2.在打包程序中找到该com组件,点击属性。在属性中有Register项,把值选择为vsdrfCOM即可。

    2022年10月13日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号