简体   繁体   中英

Define a method, call and interceptor and delegate to target with ByteBuddy?

I have an object service that has several methods, one of those methods is foo(arg1, arg2) .

Want to create a new wrapper class that:

  • has single method _foo with one additional argument
  • delegate _foo execution to an interceptor, return is ignored
  • finally, delegate call to target foo on service .

Somehow, I am failing to do so:

final List<Class<?>> parameters =
    Arrays.stream(fooMethod.getParameters())
          .map(Parameter::getType)
          .collect(Collectors.toList());

    parameters.add(AdditionalParameter.class);


final DynamicType.Unloaded unloadedType = new ByteBuddy()
    .subclass(Object.class)
    .implement(interfaceType)
    .name(service.getClass().getSimpleName() + "Dynamic")
    .defineMethod(
        "_" + methodName,
        resolveReturnType(fooMethod),
        Modifier.PUBLIC)
    .withParameters(parameters)
    .intercept(to(fooInterceptor).andThen(
        MethodCall.invoke(fooMethod).on(service)
    ))
    .make();

fooInterceptor is an InvocatiomHandler instance:

public class FooInterceptor implements InvocationHandler {
public Object invoke(
    @This final Object proxy,
    @Origin final Method method.
    @AllArguments final Object[] args) {
    ...
    }
}

The exception says that my fooService "does not accept 0 arguments".

May I call service.foo() from the interceptor - but not using reflection? I am not being able to do so (but didn't play with that part yet).

Help?

EDIT: I have no control in what methods are in service so I can't simply use to(service) with intercept call; there might be a case where ByteBuddy would not be able to find the matching method.

EDIT2: If I can just 'tell' ByteBuddy the name of target method to bind, that would be awesome. Then I could use to(service) with given hint.

You can supply a matcher to MethodDelegation to narrow down the methods to consider:

MethodDelegation.withDefaultConfiguration().filter(...).to(...)

As for your MethodCall , you need to specify what arguments to include, foo takes two arguments. Since your original arguments seems to be equivalent, you can set:

MethodCall.invoke(fooMethod).on(service).withAllArguments();

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