首页 > 解决方案 > 有没有办法通过 ByteBuddy 中的拦截器通过 MethodDescription 调用方法?

问题描述

我正在实现一个代理,它使加载的类隐式实现一个接口。接口中的方法,由代理实现,以自定义的方式调用带有特殊注释的原始类方法。但事实证明,在AgentBuilder.Transformer加载的类中仍然不存在。然而,拦截器中的代码是在类实际加载后执行的。因此拦截器中的代码可以与类方法一起使用。我可以使用MethodDescription对象调用这些方法吗?

public class CustomTransformer implements AgentBuilder.Transformer {

    public static class InstantiateInterceptor {

        private final Collection<MethodDescription> methodDescription;

        InstantiateInterceptor(Collection<MethodDescription> methodDescription) {
            this.methodDescription = methodDescription;
        }

        public Object intercept(@This Object self) {
            //
            // Call method by descriptions somewhere here
            //
            return null;
        }
    }

    @Override
    public DynamicType.Builder<?> transform(
            DynamicType.Builder<?> builder,
            TypeDescription typeDescription,
            ClassLoader classLoader,
            JavaModule module) {

        try {

            List<MethodDescription> cacheableMethods =
                    typeDescription.getDeclaredMethods().stream()
                            .filter(t -> t.getDeclaredAnnotations()
                                    .isAnnotationPresent(EnhanceMarker.class))
                            .collect(Collectors.toList());

            return builder
                    .implement(HasField.class)
                    .define(HasField.class.getMethod("value"))
                    .intercept(MethodDelegation
                            .to(new InstantiateInterceptor(cacheableMethods)));
        } catch (NoSuchMethodException ex) {
            ex.printStackTrace();
        }

        return builder;
    }
}

我可能可以通过@This对象的名称从对象中获取方法。但它需要参数类型列表,我只能得到ParameterDescription类对象的列表,它不返回参数类型。

标签: javabyte-buddy

解决方案


如果该方法在@This实例上可用,为什么不直接调用它而不进行反射?或者这个方法是生成的?在这种情况下,在接口中定义签名,实现该接口并@This在该接口上读取实例。

如果你想调用超级方法,你可以对一个实例进行同样的操作,该实例由@SuperByte Buddy 创建适当代理的位置进行注释。


推荐阅读