源码角度了解Skywalking之ClassEnhancePluginDefine拦截构造方法和类实例方法
上篇文章我们分析到ClassEnhancePluginDefine的拦截静态方法进行增强,而Skywalking初始化的时候不仅对静态方法进行拦截,构造方法和类实例方法同样会做拦截,今天我们就分析一下这一块的逻辑。
ClassEnhancePluginDefine的enhanceInstance()方法的代码有点长,我们分三块进行分析。
1. 实现EnhancedInstance接口
ClassEnhancePluginDefine的enhanceInstance()方法中实现实现EnhancedInstance接口的代码:
if (!context.isObjectExtended()) {
newClassBuilder = newClassBuilder.defineField(CONTEXT_ATTR_NAME, Object.class, ACC_PRIVATE | ACC_VOLATILE)
.implement(EnhancedInstance.class)
.intercept(FieldAccessor.ofField(CONTEXT_ATTR_NAME));
context.extendObjectCompleted();
}
创建一个新的类,类实现EnhancedInstance接口,并且类中定义private volatile Object 字段,字段名_$EnhancedClassField_ws,因为EnhancedInstance的接口定义了两个方法getSkyWalkingDynamicField()和setSkyWalkingDynamicField()方法,创建的这个新的类也会实现这两个方法
2. 拦截构造方法进行增强
ClassEnhancePluginDefine的enhanceInstance()方法中拦截构造方法的代码:
ConstructorInterceptPoint[] constructorInterceptPoints = getConstructorsInterceptPoints();
if (existedConstructorInterceptPoint) {
for (ConstructorInterceptPoint constructorInterceptPoint : constructorInterceptPoints) {
if (isBootstrapInstrumentation()) {
newClassBuilder = newClassBuilder.constructor(constructorInterceptPoint.getConstructorMatcher()).intercept(SuperMethodCall.INSTANCE
.andThen(MethodDelegation.withDefaultConfiguration()
.to(BootstrapInstrumentBoost.forInternalDelegateClass(constructorInterceptPoint.getConstructorInterceptor()))
)
);
} else {
newClassBuilder = newClassBuilder.constructor(constructorInterceptPoint.getConstructorMatcher()).intercept(SuperMethodCall.INSTANCE
.andThen(MethodDelegation.withDefaultConfiguration()
.to(new ConstructorInter(constructorInterceptPoint.getConstructorInterceptor(), classLoader))
)
);
}
}
}
这段代码就是获取构造方法的切入点,然后遍历,通过拦截器进行拦截增强,和增强静态方法的逻辑差不多,获取构造方法切入点的方法同样是抽象方法getConstructorsInterceptPoints(),具体逻辑由AbstractClassEnhancePluginDefine的子类实现,我们可以看到对应拦截器为ConstructorInter类,这个类拦截构造函数方法,同样它也是 byte-buddy 和 sky-walking 插件之间的桥梁
ConstructorInter lanjie器的intercept()方法
ConstructorInter兰姐器的intercept()方法:
public void intercept(@This Object obj,
@AllArguments Object[] allArguments) {
try {
EnhancedInstance targetObject = (EnhancedInstance)obj;
interceptor.onConstruct(targetObject, allArguments);
} catch (Throwable t) {
logger.error("ConstructorInter failure.", t);
}
}
这段代码就很简单了,直接调用InstanceConstructorInterceptor接口的onConstruct()方法对构造方法进行增强,InstanceConstructorInterceptor是实例构造函数的拦截器接口,任何想要拦截构造函数的插件都必须实现这个接口。
3. 拦截实例方法进行增强
获取切入点
InstanceMethodsInterceptPoint[] instanceMethodsInterceptPoints = getInstanceMethodsInterceptPoints();
具体逻辑同样由AbstractClassEnhancePluginDefine的子类实现
遍历拦截切入点集合,获取拦截器,拦截器同样分为可以修改参数的InstMethodsInterWithOverrideArgs拦截器和不需要修改参数的InstMethodsInter拦截器,涉及到的接口是InstanceMethodsAroundInterceptor接口,它拦截方法的调用,插件如果想拦截方法需要实现这个接口来自定义逻辑。
涉及到的拦截器在创建的时候通过构造函数创建对象,构造函数中调用了InterceptorInstanceLoader的load()方法,我们看一下这个方法
InterceptorInstanceLoader的load()
以InstMethodsInter拦截器为例:
InstMethodsInter的构造方法:
public InstMethodsInter(String instanceMethodsAroundInterceptorClassName, ClassLoader classLoader) {
try {
interceptor = InterceptorInstanceLoader.load(instanceMethodsAroundInterceptorClassName, classLoader);
} catch (Throwable t) {
throw new PluginException("Can't create InstanceMethodsAroundInterceptor.", t);
}
}
InterceptorInstanceLoader的load()方法会加载拦截器实例,并保持单例。每个目标ClassLoader 创建 一个AgentClassLoader子类,作为扩展类加载器。这个方法可以从插件、激活文件夹加载拦截器类。
总结
这篇文章主要分析了一下ClassEnhancePluginDefine类的拦截构造方法和类实例方法的增强逻辑,拦截构造方法涉及到的拦截器为ConstructorInter,涉及接口为InstanceConstructorInterceptor,插件想构造方法增强的逻辑通过实现这个接口来定义,拦截实例方法涉及到的拦截器为InstMethodsInterWithOverrideArgs和InstMethodsInter,涉及接口为InstanceMethodsAroundInterceptor接口,插件对实例方法增强的逻辑通过实现这个接口来定义
❤️ 感谢大家
如果你觉得这篇内容对你挺有有帮助的话:
- 欢迎关注我❤️,点赞 标签:拦截器,构造方法,接口,源码,ClassEnhancePluginDefine,EnhancedInstance,拦截,方法 From: https://blog.51cto.com/u_15460453/5730452