package org.skywalking.apm.agent.core.plugin.interceptor.enhance;
import net.bytebuddy.implementation.bind.annotation.AllArguments;
import net.bytebuddy.implementation.bind.annotation.FieldProxy;
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
import net.bytebuddy.implementation.bind.annotation.This;
import org.skywalking.apm.agent.core.plugin.interceptor.EnhancedClassInstanceContext;
import org.skywalking.apm.agent.core.plugin.interceptor.loader.InterceptorInstanceLoader;
import org.skywalking.apm.logging.ILog;
import org.skywalking.apm.logging.LogManager;
/**
* The actual byte-buddy's interceptor to intercept constructor methods.
* In this class, it provide a bridge between byte-buddy and sky-walking plugin.
*
* @author wusheng
*/
public class ClassConstructorInterceptor {
private static final ILog logger = LogManager.getLogger(ClassConstructorInterceptor.class);
/**
* A class full name, and instanceof {@link InstanceConstructorInterceptor}
* This name should only stay in {@link String}, the real {@link Class} type will trigger classloader failure.
* If you want to know more, please check on books about Classloader or Classloader appointment mechanism.
*/
private String constructorInterceptorClassName;
/**
* Set the name of {@link ClassConstructorInterceptor#constructorInterceptorClassName}
*
* @param constructorInterceptorClassName class full name.
*/
public ClassConstructorInterceptor(String constructorInterceptorClassName) {
this.constructorInterceptorClassName = constructorInterceptorClassName;
}
/**
* Intercept the target constructor.
*
* @param obj target class instance.
* @param accessor setter to the new added field of the target enhanced class.
* @param allArguments all constructor arguments
*/
@RuntimeType
public void intercept(@This Object obj, @FieldProxy(ClassEnhancePluginDefine.CONTEXT_ATTR_NAME) FieldSetter accessor,
@AllArguments Object[] allArguments) {
try {
InstanceConstructorInterceptor interceptor = InterceptorInstanceLoader.load(constructorInterceptorClassName, obj.getClass().getClassLoader());
EnhancedClassInstanceContext context = new EnhancedClassInstanceContext();
accessor.setValue(context);
ConstructorInvokeContext interceptorContext = new ConstructorInvokeContext(obj, allArguments);
interceptor.onConstruct(context, interceptorContext);
} catch (Throwable t) {
logger.error("ClassConstructorInterceptor failure.", t);
}
}
}