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

举报
周杰伦本人 发表于 2022/10/30 18:01:08 2022/10/30
【摘要】 源码角度了解Skywalking之ClassEnhancePluginDefine拦截构造方法和类实例方法我们分析到ClassEnhancePluginDefine的拦截静态方法进行增强,而Skywalking初始化的时候不仅对静态方法进行拦截,构造方法和类实例方法同样会做拦截,今天我们就分析一下这一块的逻辑。ClassEnhancePluginDefine的enhanceInstance...

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

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。