package com.github.ompc.greys.core.advisor;
import com.github.ompc.greys.core.util.collection.GaStack;
import com.github.ompc.greys.core.util.collection.ThreadUnsafeGaStack;
/**
* 反射版的方法通知调用通知适配器
* Created by oldmanpushcart@gmail.com on 15/7/24.
*/
public abstract class ReflectAdviceTracingListenerAdapter
extends ReflectAdviceListenerAdapter implements AdviceTracingListener {
// 修复问题 #78
// 在当前类的<init>调用之前JVM会先调用super.<init>, 这些步骤只能被暂时跳过
// 所以这里需要记录下被掉过的信息
private final ThreadLocal<GaStack<Tracing>> skipSuperInitStackRef = new ThreadLocal<GaStack<Tracing>>() {
@Override
protected GaStack<Tracing> initialValue() {
return new ThreadUnsafeGaStack<Tracing>();
}
};
// before()是否已经被调用,用于修正 #78 问题
private final ThreadLocal<Boolean> isBeforeCalledRef = new ThreadLocal<Boolean>() {
@Override
protected Boolean initialValue() {
return false;
}
};
@Override
void beforeHook() {
super.beforeHook();
isBeforeCalledRef.set(true);
}
@Override
void finishHook() {
super.finishHook();
isBeforeCalledRef.remove();
}
@Override
final public void invokeBeforeTracing(Integer tracingLineNumber, String tracingClassName, String tracingMethodName, String tracingMethodDesc) throws Throwable {
// 如果before()方法尚未被调用
// 为 #78 问题所触发的情况
if (!isBeforeCalledRef.get()) {
skipSuperInitStackRef.get().push(new Tracing(tracingLineNumber, tracingClassName, tracingMethodName, tracingMethodDesc));
return;
}
tracingInvokeBefore(tracingLineNumber, tracingClassName, tracingMethodName, tracingMethodDesc);
}
// 校验之前有多少步骤需要被跳过
private void popSuperInit() throws Throwable {
final GaStack<Tracing> stack = skipSuperInitStackRef.get();
if (!stack.isEmpty()) {
final Tracing tracing = stack.pop();
tracingInvokeBefore(
tracing.tracingLineNumber,
tracing.tracingClassName,
tracing.tracingMethodName,
tracing.tracingMethodDesc
);
}
}
@Override
final public void invokeThrowTracing(Integer tracingLineNumber, String tracingClassName, String tracingMethodName, String tracingMethodDesc, String throwException) throws Throwable {
popSuperInit();
tracingInvokeThrowing(tracingLineNumber, tracingClassName, tracingMethodName, tracingMethodDesc, throwException);
}
@Override
final public void invokeAfterTracing(Integer tracingLineNumber, String tracingClassName, String tracingMethodName, String tracingMethodDesc) throws Throwable {
popSuperInit();
tracingInvokeAfter(tracingLineNumber, tracingClassName, tracingMethodName, tracingMethodDesc);
}
public void tracingInvokeBefore(
Integer tracingLineNumber, String tracingClassName, String tracingMethodName, String tracingMethodDesc) throws Throwable {
}
public void tracingInvokeAfter(
Integer tracingLineNumber, String tracingClassName, String tracingMethodName, String tracingMethodDesc) throws Throwable {
}
public void tracingInvokeThrowing(
Integer tracingLineNumber, String tracingClassName, String tracingMethodName, String tracingMethodDesc, String throwException) throws Throwable {
}
static class Tracing {
private final Integer tracingLineNumber;
private final String tracingClassName;
private final String tracingMethodName;
private final String tracingMethodDesc;
Tracing(Integer tracingLineNumber, String tracingClassName, String tracingMethodName, String tracingMethodDesc) {
this.tracingLineNumber = tracingLineNumber;
this.tracingClassName = tracingClassName;
this.tracingMethodName = tracingMethodName;
this.tracingMethodDesc = tracingMethodDesc;
}
}
}