简体   繁体   中英

Is there a way to invoke a method by MethodDescription from the interceptor in ByteBuddy?

I'm implementing an agent that makes the loaded class implicitly implement an interface. Method in the interface, implemented by the agent, calls original class methods, marked with a special annotation, in a custom way. But it turns out that in AgentBuilder.Transformer the loaded class still not exists. However the code inside the interceptor is executed after the class has actually being loaded. So the code inside interceptor could work with the class methods. Can I call that methods using MethodDescription objects?

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;
    }
}

I could probably get the method from @This object by its name. But it requires parameter types list, and I can get only list of ParameterDescription class objects, and it doesn't return argument types.

If the method is available on the @This instance, why would you not just call it without reflection? Or is this method generated? In that case, define the signature in an interface, implement that interface and read the @This instance upon this interface.

If you want to invoke super-methods, you can do the same trip with an instance annotated by @Super where Byte Buddy creates an appropriate proxy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM