使用 1:通过 advice 支持主 JAR 访问插件类 public class CloudAnalyticsDynamicWithOriginAdvisor { /** * must public and not final */ @SuppressWarnings("FieldMayBeFinal") public static DynamicAccessor INJECT_ACCESSOR = null; @Advice.OnMethodEnter public static DynamicAccessor onMethodEnter(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object origin, @Advice.Origin Method method, @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] arguments) { DynamicAccessor accessor = INJECT_ACCESSOR; if (accessor != null) { try { accessor.beforeExecute(origin, method, arguments); } catch (Throwable t) { FineLoggerFactory.getLogger().error(t.getMessage(), t); } } return accessor; } @Advice.OnMethodExit(onThrowable = Exception.class) public static void onMethodExit(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object origin, @Advice.Origin Method method, @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] arguments, @Advice.Return(readOnly = true, typing = Assigner.Typing.DYNAMIC) Object result, @Advice.Thrown(readOnly = true, typing = Assigner.Typing.DYNAMIC) Exception e, @Advice.Enter(typing = Assigner.Typing.DYNAMIC) DynamicAccessor accessor) { if (accessor != null) { if (e != null) { try { accessor.exception(origin, method, arguments, e); } catch (Throwable t) { FineLoggerFactory.getLogger().error(e.getMessage(), e); FineLoggerFactory.getLogger().error(t.getMessage(), t); } } try { accessor.afterExecute(origin, method, arguments, result); } catch (Throwable t) { FineLoggerFactory.getLogger().error(t.getMessage(), t); } } } } private Advisor create(DynamicAccessor accessor) { ClassLoader classLoader = getAppClassLoader(); String key = accessor.key(); String dynamicName = "com.fr.dynamic." + key + ".CloudAnalyticsDynamicAdvisor"; Accessor ar = accessor.getClass().getAnnotation(Accessor.class); DynamicType.Unloaded<?> advisorType = new ByteBuddy() .redefine(ar.type()) .name(dynamicName) // 在初始化时,将对象注入到类中,从而能够访问插件类 .initializer(new StaticFieldInitializer("INJECT_ACCESSOR", accessor)) .make(); // make it loaded by the app class loader advisorType.load(classLoader, ClassLoadingStrategy.withFallback(new Callable<Object>() { @Override public Object call() throws Exception { return MethodHandles.lookup(); } })); ClassFileLocator fileLocator = new ClassFileLocator.Compound( ClassFileLocator.Simple.of(dynamicName, advisorType.getBytes()), ClassFileLocator.ForClassLoader.of(classLoader) ); TypeDescription advisorTypeDesc = advisorType.getTypeDescription(); return new Advisor(advisorTypeDesc, fileLocator); } 核心原理是在 class 加载到 classloader 时,通过静态方案将对象传入实例化后的 object 中。 使用 2:通过 intercept 支持主 JAR 访问插件类 Skywalking 原理分析.md