使用 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