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