本文主要研究一下skywalking的AbstractClassEnhancePluginDefine
skywalking-6.6.0/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java
public abstract class AbstractClassEnhancePluginDefine { private static final ILog logger = LogManager.getLogger(AbstractClassEnhancePluginDefine.class); /** * Main entrance of enhancing the class. * * @param typeDescription target class description. * @param builder byte-buddy's builder to manipulate target class's bytecode. * @param classLoader load the given transformClass * @return the new builder, or <code>null</code> if not be enhanced. * @throws PluginException when set builder failure. */ public DynamicType.Builder<?> define(TypeDescription typeDescription, DynamicType.Builder<?> builder, ClassLoader classLoader, EnhanceContext context) throws PluginException { String interceptorDefineClassName = this.getClass().getName(); String transformClassName = typeDescription.getTypeName(); if (StringUtil.isEmpty(transformClassName)) { logger.warn("classname of being intercepted is not defined by {}.", interceptorDefineClassName); return null; } logger.debug("prepare to enhance class {} by {}.", transformClassName, interceptorDefineClassName); /** * find witness classes for enhance class */ String[] witnessClasses = witnessClasses(); if (witnessClasses != null) { for (String witnessClass : witnessClasses) { if (!WitnessClassFinder.INSTANCE.exist(witnessClass, classLoader)) { logger.warn("enhance class {} by plugin {} is not working. Because witness class {} is not existed.", transformClassName, interceptorDefineClassName, witnessClass); return null; } } } /** * find origin class source code for interceptor */ DynamicType.Builder<?> newClassBuilder = this.enhance(typeDescription, builder, classLoader, context); context.initializationStageCompleted(); logger.debug("enhance class {} by {} completely.", transformClassName, interceptorDefineClassName); return newClassBuilder; } protected abstract DynamicType.Builder<?> enhance(TypeDescription typeDescription, DynamicType.Builder<?> newClassBuilder, ClassLoader classLoader, EnhanceContext context) throws PluginException; /** * Define the {@link ClassMatch} for filtering class. * * @return {@link ClassMatch} */ protected abstract ClassMatch enhanceClass(); /** * Witness classname list. Why need witness classname? Let's see like this: A library existed two released versions * (like 1.0, 2.0), which include the same target classes, but because of version iterator, they may have the same * name, but different methods, or different method arguments list. So, if I want to target the particular version * (let's say 1.0 for example), version number is obvious not an option, this is the moment you need "Witness * classes". You can add any classes only in this particular release version ( something like class * com.company.1.x.A, only in 1.0 ), and you can achieve the goal. * * @return */ protected String[] witnessClasses() { return new String[] {}; } public boolean isBootstrapInstrumentation() { return false; } /** * Constructor methods intercept point. See {@link ConstructorInterceptPoint} * * @return collections of {@link ConstructorInterceptPoint} */ public abstract ConstructorInterceptPoint[] getConstructorsInterceptPoints(); /** * Instance methods intercept point. See {@link InstanceMethodsInterceptPoint} * * @return collections of {@link InstanceMethodsInterceptPoint} */ public abstract InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints(); /** * Static methods intercept point. See {@link StaticMethodsInterceptPoint} * * @return collections of {@link StaticMethodsInterceptPoint} */ public abstract StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints(); } 复制代码
skywalking-6.6.0/apm-sniffer/apm-agent/src/main/java/org/apache/skywalking/apm/agent/SkyWalkingAgent.java
private static class Transformer implements AgentBuilder.Transformer { private PluginFinder pluginFinder; Transformer(PluginFinder pluginFinder) { this.pluginFinder = pluginFinder; } @Override public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) { List<AbstractClassEnhancePluginDefine> pluginDefines = pluginFinder.find(typeDescription); if (pluginDefines.size() > 0) { DynamicType.Builder<?> newBuilder = builder; EnhanceContext context = new EnhanceContext(); for (AbstractClassEnhancePluginDefine define : pluginDefines) { DynamicType.Builder<?> possibleNewBuilder = define.define(typeDescription, newBuilder, classLoader, context); if (possibleNewBuilder != null) { newBuilder = possibleNewBuilder; } } if (context.isEnhanced()) { logger.debug("Finish the prepare stage for {}.", typeDescription.getName()); } return newBuilder; } logger.debug("Matched class {}, but ignore by finding mechanism.", typeDescription.getTypeName()); return builder; } } 复制代码
AbstractClassEnhancePluginDefine提供了define方法,它主要是通过enhance方法创建newClassBuilder,然后执行context.initializationStageCompleted()并返回newClassBuilder;它定义了enhance、enhanceClass、witnessClasses、getConstructorsInterceptPoints、getInstanceMethodsInterceptPoints、getStaticMethodsInterceptPoints抽象方法供子类实现