首页 > 编程语言 >源码角度了解Skywalking之ClassEnhancePluginDefine拦截构造方法和类实例方法

源码角度了解Skywalking之ClassEnhancePluginDefine拦截构造方法和类实例方法

时间:2022-10-03 21:03:40浏览次数:60  
标签:拦截器 构造方法 接口 源码 ClassEnhancePluginDefine EnhancedInstance 拦截 方法

源码角度了解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接口,插件对实例方法增强的逻辑通过实现这个接口来定义

❤️ 感谢大家

如果你觉得这篇内容对你挺有有帮助的话:

  1. 欢迎关注我❤️,点赞

    标签:拦截器,构造方法,接口,源码,ClassEnhancePluginDefine,EnhancedInstance,拦截,方法
    From: https://blog.51cto.com/u_15460453/5730452

相关文章