/*
 * Copyright 2014 - 2019 Rafael Winterhalter
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.bytebuddy.implementation;

import net.bytebuddy.build.HashCodeAndEqualsPlugin;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.method.MethodList;
import net.bytebuddy.description.type.TypeDefinition;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.scaffold.FieldLocator;
import net.bytebuddy.dynamic.scaffold.InstrumentedType;
import net.bytebuddy.dynamic.scaffold.MethodGraph;
import net.bytebuddy.implementation.bind.MethodDelegationBinder;
import net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder;
import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
import net.bytebuddy.implementation.bytecode.Duplication;
import net.bytebuddy.implementation.bytecode.StackManipulation;
import net.bytebuddy.implementation.bytecode.TypeCreation;
import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.implementation.bytecode.member.FieldAccess;
import net.bytebuddy.implementation.bytecode.member.MethodInvocation;
import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.utility.CompoundList;
import net.bytebuddy.utility.RandomString;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static net.bytebuddy.matcher.ElementMatchers.*;

This implementation delegates an method call to another method which can either be static by providing a reference to a Class or an instance method when another object is provided. The potential targets of the method delegation can further be filtered by applying a filter. The method delegation can be customized by invoking the MethodDelegation's several builder methods.

Without any customization, the method delegation will work as follows:

Binding an instrumented method to a given delegate method

 

A method will be bound parameter by parameter. Considering a method Foo#bar being bound to a method Qux#baz, the method delegation will be decided on basis of the following annotations:
  • Argument: This annotation will bind the n-th parameter of Foo#bar to that parameter of Qux#bazthat is annotated with this annotation where n is the obligatory argument of the @Argument annotation.
  • AllArguments: This annotation will assign a collection of all parameters of Foo#bar to that parameter of Qux#baz that is annotated with AllArguments.
  • This: A parameter of Qux#baz that is annotated with This will be assigned the instance that is instrumented for a non-static method.
  • Super: A parameter that is annotated with this annotation is assigned a proxy that allows calling an instrumented type's super methods.
  • Default: A parameter that is annotated with this annotation is assigned a proxy that allows calling an instrumented type's directly implemented interfaces' default methods.
  • SuperCall: A parameter of Qux#baz that is annotated with SuperCall will be assigned an instance of a type implementing both Runnable and Callable which will invoke the instrumented method on the invocation of either interface's method. The call is made using the original arguments of the method invocation. The return value is only emitted for the Callable.call() method which additionally requires to catch any unchecked exceptions that might be thrown by the original method's implementation. If a source method is abstract, using this annotation excludes the method with this parameter annotation from being bound to this source method.
  • DefaultCall: This annotation is similar to the SuperCall annotation but it invokes a default method that is compatible to this method. If a source method does not represent a default method, using this annotation excludes the method with this parameter annotation from being bound to this source method.
  • The SuperMethod or DefaultMethod annotations can be used on any parameter type that is assignable from the Method type. the parameter is bound a method instance that allows for the reflective invocation of a super or default method. Note that this method is not equal to the intercepted method but represents a synthetic accessor method. Using this annotation also causes this accessor to be public which allows its outside invocation without any access checks by a security manager.
  • Origin: A parameter of Qux#baz that is annotated with Origin is assigned a reference to either a Method, a Constructor, a java.lang.reflect.Executable or a Class instance. A Method-typed, Constructor or Executable parameter is assigned a reference to the original method that is instrumented. A Class-typed parameter is assigned the type of the caller. Furthermore, MethodType and MethodHandle parameters are also supported. When using the annotation on a String type, the intercepted method's toString value is injected. The same holds for a parameter of type int that receives the modifiers of the instrumented method.
  • StubValue: Assigns the (boxed) default value of the intercepted method's return type to the parameter. If the return type is void, null is assigned.
  • Empty: Assigns the parameter type's default value, i.e. null for a reference type or zero for primitive types. This is an opportunity to ignore a parameter.
  • Pipe: A parameter that is annotated with this annotation is assigned a proxy for forwarding the source method invocation to another instance of the same type as the declaring type of the intercepted method. This annotation needs to be installed and explicitly registered before it can be used. See the Pipe annotation's documentation for further information on how this can be done.
  • Morph: The morph annotation is similar to the SuperCall annotation but allows to explicitly define and therewith alter the arguments that are handed to the super method. This annotation needs to be installed and explicitly registered before it can be used. See the documentation to the annotation for further information.
  • FieldValue: Allows to access a field's value at the time of the method invocation. The field's value is directly assigned to the annotated parameter.
  • FieldProxy: Allows to access fields via getter and setter proxies. This annotation needs to be installed and explicitly registered before it can be used. Note that any field access requires boxing such that a use of FieldAccessor in combination with andThen(Implementation) might be a more performant alternative for implementing field getters and setters.
If a method is not annotated with any of the above methods, it will be treated as if it was annotated Argument using the next unbound parameter index of the source method as its parameter. This means that a method Qux#baz(@Argument(2) Object p1, Object p2, @Argument(0) Object p3 would be treated as if p2 was annotated with @Argument(1).

 

In addition, the RuntimeType annotation can instruct a parameter to be bound by a Assigner with considering the runtime type of the parameter.

 

Selecting among different methods that can be used for binding a method of the instrumented type

 

When deciding between two methods Foo#bar and Foo#qux that could both be used to delegating a method call, the following consideration is applied in the given order:
  1. BindingPriority: A method that is annotated with this annotation is given a specific priority where the default priority is set to BindingPriority.DEFAULT for non-annotated method. A method with a higher priority is considered a better target for delegation.
  2. DeclaringTypeResolver: If a target method is declared by a more specific type than another method, the method with the most specific type is bound.
  3. MethodNameEqualityResolver: If a source method Baz#qux is the source method, it will rather be assigned to Foo#qux because of their equal names. Similar names and case-insensitive equality are not considered.
  4. ArgumentTypeResolver: The most specific type resolver will consider all bindings that are using the Argument annotation for resolving a binding conflict. In this context, the resolution will equal the most-specific type resolution that is performed by the Java compiler. This means that a source method Bar#baz(String) will rather be bound to a method Foo#bar(String) than Foo#qux(Object) because the String type is more specific than the Object type. If two methods are equally adequate by their parameter types, then the method with the higher numbers of @Argument annotated parameters is considered as the better delegation target.
  5. ParameterLengthResolver: If a target methods has a higher number of total parameters that were successfully bound, the method with the higher number will be considered as the better delegation target.

Additionally, if a method is annotated by IgnoreForBinding, it is never considered as a target for a method delegation.

Important: For invoking a method on another instance, use the MethodCall implementation. A method delegation intends to bind a interceptor class and its resolution algorithm will not necessarily yield a delegation to the intercepted method.

See Also:
/** * This implementation delegates an method call to another method which can either be {@code static} by providing * a reference to a {@link java.lang.Class} or an instance method when another object is provided. The potential * targets of the method delegation can further be filtered by applying a filter. The method delegation can be * customized by invoking the {@code MethodDelegation}'s several builder methods. * <h3>Without any customization, the method delegation will work as follows:</h3> * <span style="text-decoration: underline">Binding an instrumented method to a given delegate method</span> * <p>&nbsp;</p> * A method will be bound parameter by parameter. Considering a method {@code Foo#bar} being bound to a method * {@code Qux#baz}, the method delegation will be decided on basis of the following annotations: * <ul> * <li>{@link net.bytebuddy.implementation.bind.annotation.Argument}: * This annotation will bind the {@code n}-th parameter of {@code Foo#bar} to that parameter of {@code Qux#baz}that * is annotated with this annotation where {@code n} is the obligatory argument of the {@code @Argument} annotation.</li> * <li>{@link net.bytebuddy.implementation.bind.annotation.AllArguments}: * This annotation will assign a collection of all parameters of {@code Foo#bar} to that parameter of {@code Qux#baz} * that is annotated with {@code AllArguments}.</li> * <li>{@link net.bytebuddy.implementation.bind.annotation.This}: A parameter * of {@code Qux#baz} that is annotated with {@code This} will be assigned the instance that is instrumented for * a non-static method.</li> * <li>{@link net.bytebuddy.implementation.bind.annotation.Super}: A parameter that is annotated with * this annotation is assigned a proxy that allows calling an instrumented type's super methods.</li> * <li>{@link net.bytebuddy.implementation.bind.annotation.Default}: A parameter that is annotated with * this annotation is assigned a proxy that allows calling an instrumented type's directly implemented interfaces' * default methods.</li> * <li>{@link net.bytebuddy.implementation.bind.annotation.SuperCall}: A parameter * of {@code Qux#baz} that is annotated with {@code SuperCall} will be assigned an instance of a type implementing both * {@link java.lang.Runnable} and {@link java.util.concurrent.Callable} which will invoke the instrumented method on the * invocation of either interface's method. The call is made using the original arguments of the method invocation. * The return value is only emitted for the {@link java.util.concurrent.Callable#call()} method which additionally * requires to catch any unchecked exceptions that might be thrown by the original method's implementation. If a * source method is abstract, using this annotation excludes the method with this parameter annotation from being bound * to this source method. * </li> * <li>{@link net.bytebuddy.implementation.bind.annotation.DefaultCall}: * This annotation is similar to the {@link net.bytebuddy.implementation.bind.annotation.SuperCall} * annotation but it invokes a default method that is compatible to this method. If a source method does not represent * a default method, using this annotation excludes the method with this parameter annotation from being bound to this * source method.</li> * <li>The {@link net.bytebuddy.implementation.bind.annotation.SuperMethod} or * {@link net.bytebuddy.implementation.bind.annotation.DefaultMethod} annotations can be used on any parameter type * that is assignable from the {@link java.lang.reflect.Method} type. the parameter is bound a method instance that * allows for the reflective invocation of a super or default method. Note that this method is not equal to the intercepted * method but represents a synthetic accessor method. Using this annotation also causes this accessor to be {@code public} * which allows its outside invocation without any access checks by a security manager.</li> * <li>{@link net.bytebuddy.implementation.bind.annotation.Origin}: A parameter of * {@code Qux#baz} that is annotated with {@code Origin} is assigned a reference to either a {@link java.lang.reflect.Method}, * a {@link java.lang.reflect.Constructor}, a {@code java.lang.reflect.Executable} or a {@link java.lang.Class} instance. * A {@code Method}-typed, {@code Constructor} or {@code Executable} parameter is assigned a reference to the original * method that is instrumented. A {@code Class}-typed parameter is assigned the type of the caller. Furthermore, {@code MethodType} * and {@code MethodHandle} parameters are also supported. When using the annotation on a {@link java.lang.String} type, * the intercepted method's {@code toString} value is injected. The same holds for a parameter of type {@code int} that receives * the modifiers of the instrumented method.</li> * <li>{@link net.bytebuddy.implementation.bind.annotation.StubValue}: Assigns the (boxed) default value of the * intercepted method's return type to the parameter. If the return type is {@code void}, {@code null} is assigned.</li> * <li>{@link net.bytebuddy.implementation.bind.annotation.Empty}: Assigns the parameter type's * default value, i.e. {@code null} for a reference type or zero for primitive types. This is an opportunity to * ignore a parameter.</li> * <li>{@link net.bytebuddy.implementation.bind.annotation.Pipe}: A parameter that is annotated * with this annotation is assigned a proxy for forwarding the source method invocation to another instance of the * same type as the declaring type of the intercepted method. <b>This annotation needs to be installed and explicitly * registered before it can be used.</b> See the {@link net.bytebuddy.implementation.bind.annotation.Pipe} * annotation's documentation for further information on how this can be done.</li> * <li>{@link net.bytebuddy.implementation.bind.annotation.Morph}: The morph annotation is similar to * the {@link net.bytebuddy.implementation.bind.annotation.SuperCall} annotation but allows to * explicitly define and therewith alter the arguments that are handed to the super method. <b>This annotation needs * to be installed and explicitly registered before it can be used.</b> See the documentation to the annotation for * further information.</li> * <li>{@link net.bytebuddy.implementation.bind.annotation.FieldValue}: Allows to access a field's value at the time * of the method invocation. The field's value is directly assigned to the annotated parameter.</li> * <li>{@link net.bytebuddy.implementation.bind.annotation.FieldProxy}: Allows to access fields via getter * and setter proxies. <b>This annotation needs to be installed and explicitly registered before it can be used.</b> * Note that any field access requires boxing such that a use of {@link net.bytebuddy.implementation.FieldAccessor} in * combination with {@link net.bytebuddy.implementation.MethodDelegation#andThen(Implementation)} might be a more * performant alternative for implementing field getters and setters.</li> * </ul> * If a method is not annotated with any of the above methods, it will be treated as if it was annotated * {@link net.bytebuddy.implementation.bind.annotation.Argument} using the next * unbound parameter index of the source method as its parameter. This means that a method * {@code Qux#baz(@Argument(2) Object p1, Object p2, @Argument(0) Object p3} would be treated as if {@code p2} was annotated * with {@code @Argument(1)}. * <p>&nbsp;</p> * In addition, the {@link net.bytebuddy.implementation.bind.annotation.RuntimeType} * annotation can instruct a parameter to be bound by a * {@link net.bytebuddy.implementation.bytecode.assign.Assigner} with considering the * runtime type of the parameter. * <p>&nbsp;</p> * <span style="text-decoration: underline">Selecting among different methods that can be used for binding a method * of the instrumented type</span> * <p>&nbsp;</p> * When deciding between two methods {@code Foo#bar} and {@code Foo#qux} that could both be used to delegating a * method call, the following consideration is applied in the given order: * <ol> * <li>{@link net.bytebuddy.implementation.bind.annotation.BindingPriority}: * A method that is annotated with this annotation is given a specific priority where the default priority is set * to {@link net.bytebuddy.implementation.bind.annotation.BindingPriority#DEFAULT} * for non-annotated method. A method with a higher priority is considered a better target for delegation.</li> * <li>{@link net.bytebuddy.implementation.bind.DeclaringTypeResolver}: * If a target method is declared by a more specific type than another method, the method with the most specific * type is bound.</li> * <li>{@link net.bytebuddy.implementation.bind.MethodNameEqualityResolver}: * If a source method {@code Baz#qux} is the source method, it will rather be assigned to {@code Foo#qux} because * of their equal names. Similar names and case-insensitive equality are not considered.</li> * <li>{@link net.bytebuddy.implementation.bind.ArgumentTypeResolver}: * The most specific type resolver will consider all bindings that are using the * {@link net.bytebuddy.implementation.bind.annotation.Argument} * annotation for resolving a binding conflict. In this context, the resolution will equal the most-specific * type resolution that is performed by the Java compiler. This means that a source method {@code Bar#baz(String)} * will rather be bound to a method {@code Foo#bar(String)} than {@code Foo#qux(Object)} because the {@code String} * type is more specific than the {@code Object} type. If two methods are equally adequate by their parameter types, * then the method with the higher numbers of {@code @Argument} annotated parameters is considered as the better * delegation target.</li> * <li>{@link net.bytebuddy.implementation.bind.ParameterLengthResolver}: * If a target methods has a higher number of total parameters that were successfully bound, the method with * the higher number will be considered as the better delegation target.</li> * </ol> * <p> * Additionally, if a method is annotated by * {@link net.bytebuddy.implementation.bind.annotation.IgnoreForBinding}, * it is never considered as a target for a method delegation. * </p> * <p> * <b>Important</b>: For invoking a method on another instance, use the {@link MethodCall} implementation. A method delegation * intends to bind a interceptor class and its resolution algorithm will not necessarily yield a delegation to the intercepted * method. * </p> * * @see MethodCall * @see net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder.ParameterBinder.ForFixedValue */
@HashCodeAndEqualsPlugin.Enhance public class MethodDelegation implements Implementation.Composable {
The implementation delegate for this method delegation.
/** * The implementation delegate for this method delegation. */
private final ImplementationDelegate implementationDelegate;
A list of ParameterBinders to be used by this method delegation.
/** * A list of {@link net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder.ParameterBinder}s * to be used by this method delegation. */
private final List<TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders;
The AmbiguityResolver to be used by this method delegation.
/** * The {@link net.bytebuddy.implementation.bind.MethodDelegationBinder.AmbiguityResolver} * to be used by this method delegation. */
private final MethodDelegationBinder.AmbiguityResolver ambiguityResolver;
The termination handler to apply.
/** * The termination handler to apply. */
private final TargetMethodAnnotationDrivenBinder.TerminationHandler terminationHandler;
The binding resolver being used to select the relevant method binding.
/** * The binding resolver being used to select the relevant method binding. */
private final MethodDelegationBinder.BindingResolver bindingResolver;
The Assigner to be used by this method delegation.
/** * The {@link net.bytebuddy.implementation.bytecode.assign.Assigner} to be used by this method delegation. */
private final Assigner assigner;
Creates a new method delegation.
Params:
  • implementationDelegate – The implementation delegate to use by this method delegator.
  • parameterBinders – The parameter binders to use by this method delegator.
  • ambiguityResolver – The ambiguity resolver to use by this method delegator.
  • bindingResolver – The binding resolver being used to select the relevant method binding.
/** * Creates a new method delegation. * * @param implementationDelegate The implementation delegate to use by this method delegator. * @param parameterBinders The parameter binders to use by this method delegator. * @param ambiguityResolver The ambiguity resolver to use by this method delegator. * @param bindingResolver The binding resolver being used to select the relevant method binding. */
protected MethodDelegation(ImplementationDelegate implementationDelegate, List<TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders, MethodDelegationBinder.AmbiguityResolver ambiguityResolver, MethodDelegationBinder.BindingResolver bindingResolver) { this(implementationDelegate, parameterBinders, ambiguityResolver, MethodDelegationBinder.TerminationHandler.Default.RETURNING, bindingResolver, Assigner.DEFAULT); }
Creates a new method delegation.
Params:
  • implementationDelegate – The implementation delegate to use by this method delegator.
  • parameterBinders – The parameter binders to use by this method delegator.
  • ambiguityResolver – The ambiguity resolver to use by this method delegator.
  • terminationHandler – The termination handler to apply.
  • bindingResolver – The binding resolver being used to select the relevant method binding.
  • assigner – The assigner to be supplied by this method delegator.
/** * Creates a new method delegation. * * @param implementationDelegate The implementation delegate to use by this method delegator. * @param parameterBinders The parameter binders to use by this method delegator. * @param ambiguityResolver The ambiguity resolver to use by this method delegator. * @param terminationHandler The termination handler to apply. * @param bindingResolver The binding resolver being used to select the relevant method binding. * @param assigner The assigner to be supplied by this method delegator. */
private MethodDelegation(ImplementationDelegate implementationDelegate, List<TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders, MethodDelegationBinder.AmbiguityResolver ambiguityResolver, TargetMethodAnnotationDrivenBinder.TerminationHandler terminationHandler, MethodDelegationBinder.BindingResolver bindingResolver, Assigner assigner) { this.implementationDelegate = implementationDelegate; this.parameterBinders = parameterBinders; this.terminationHandler = terminationHandler; this.ambiguityResolver = ambiguityResolver; this.bindingResolver = bindingResolver; this.assigner = assigner; }
Delegates any intercepted method to invoke a static method that is declared by the supplied type. To be considered a valid delegation target, the target method must be visible and accessible to the instrumented type. This is the case if the target type is either public or in the same package as the instrumented type and if the target method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the interception is targeting the instrumented type.
Params:
  • type – The target type for the delegation.
Returns:A method delegation that redirects method calls to a static method of the supplied type.
/** * Delegates any intercepted method to invoke a {@code static} method that is declared by the supplied type. To be considered * a valid delegation target, the target method must be visible and accessible to the instrumented type. This is the case if * the target type is either public or in the same package as the instrumented type and if the target method is either public * or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if * the interception is targeting the instrumented type. * * @param type The target type for the delegation. * @return A method delegation that redirects method calls to a static method of the supplied type. */
public static MethodDelegation to(Class<?> type) { return withDefaultConfiguration().to(type); }
Delegates any intercepted method to invoke a static method that is declared by the supplied type. To be considered a valid delegation target, the target method must be visible and accessible to the instrumented type. This is the case if the target type is either public or in the same package as the instrumented type and if the target method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the interception is targeting the instrumented type.
Params:
  • typeDescription – The target type for the delegation.
Returns:A method delegation that redirects method calls to a static method of the supplied type.
/** * Delegates any intercepted method to invoke a {@code static} method that is declared by the supplied type. To be considered * a valid delegation target, the target method must be visible and accessible to the instrumented type. This is the case if * the target type is either public or in the same package as the instrumented type and if the target method is either public * or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if * the interception is targeting the instrumented type. * * @param typeDescription The target type for the delegation. * @return A method delegation that redirects method calls to a static method of the supplied type. */
public static MethodDelegation to(TypeDescription typeDescription) { return withDefaultConfiguration().to(typeDescription); }
Delegates any intercepted method to invoke a non-static method that is declared by the supplied type's instance or any of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • target – The target instance for the delegation.
Returns:A method delegation that redirects method calls to a static method of the supplied type.
/** * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param target The target instance for the delegation. * @return A method delegation that redirects method calls to a static method of the supplied type. */
public static MethodDelegation to(Object target) { return withDefaultConfiguration().to(target); }
Delegates any intercepted method to invoke a non-static method that is declared by the supplied type's instance or any of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • target – The target instance for the delegation.
  • methodGraphCompiler – The method graph compiler to use.
Returns:A method delegation that redirects method calls to a static method of the supplied type.
/** * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param target The target instance for the delegation. * @param methodGraphCompiler The method graph compiler to use. * @return A method delegation that redirects method calls to a static method of the supplied type. */
public static MethodDelegation to(Object target, MethodGraph.Compiler methodGraphCompiler) { return withDefaultConfiguration().to(target, methodGraphCompiler); }
Delegates any intercepted method to invoke a non-static method that is declared by the supplied type's instance or any of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • target – The target instance for the delegation.
  • fieldName – The name of the field that is holding the target instance.
Returns:A method delegation that redirects method calls to a static method of the supplied type.
/** * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param target The target instance for the delegation. * @param fieldName The name of the field that is holding the {@code target} instance. * @return A method delegation that redirects method calls to a static method of the supplied type. */
public static MethodDelegation to(Object target, String fieldName) { return withDefaultConfiguration().to(target, fieldName); }
Delegates any intercepted method to invoke a non-static method that is declared by the supplied type's instance or any of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • target – The target instance for the delegation.
  • fieldName – The name of the field that is holding the target instance.
  • methodGraphCompiler – The method graph compiler to use.
Returns:A method delegation that redirects method calls to a static method of the supplied type.
/** * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param target The target instance for the delegation. * @param fieldName The name of the field that is holding the {@code target} instance. * @param methodGraphCompiler The method graph compiler to use. * @return A method delegation that redirects method calls to a static method of the supplied type. */
public static MethodDelegation to(Object target, String fieldName, MethodGraph.Compiler methodGraphCompiler) { return withDefaultConfiguration().to(target, fieldName, methodGraphCompiler); }
Delegates any intercepted method to invoke a non-static method that is declared by the supplied type's instance or any of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • target – The target instance for the delegation.
  • type – The most specific type of which target should be considered. Must be a super type of the target's actual type.
Returns:A method delegation that redirects method calls to a static method of the supplied type.
/** * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param target The target instance for the delegation. * @param type The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type. * @return A method delegation that redirects method calls to a static method of the supplied type. */
public static MethodDelegation to(Object target, Type type) { return withDefaultConfiguration().to(target, type); }
Delegates any intercepted method to invoke a non-static method that is declared by the supplied type's instance or any of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • target – The target instance for the delegation.
  • type – The most specific type of which target should be considered. Must be a super type of the target's actual type.
  • methodGraphCompiler – The method graph compiler to use.
Returns:A method delegation that redirects method calls to a static method of the supplied type.
/** * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param target The target instance for the delegation. * @param type The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type. * @param methodGraphCompiler The method graph compiler to use. * @return A method delegation that redirects method calls to a static method of the supplied type. */
public static MethodDelegation to(Object target, Type type, MethodGraph.Compiler methodGraphCompiler) { return withDefaultConfiguration().to(target, type, methodGraphCompiler); }
Delegates any intercepted method to invoke a non-static method that is declared by the supplied type's instance or any of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • target – The target instance for the delegation.
  • type – The most specific type of which target should be considered. Must be a super type of the target's actual type.
  • fieldName – The name of the field that is holding the target instance.
Returns:A method delegation that redirects method calls to a static method of the supplied type.
/** * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param target The target instance for the delegation. * @param type The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type. * @param fieldName The name of the field that is holding the {@code target} instance. * @return A method delegation that redirects method calls to a static method of the supplied type. */
public static MethodDelegation to(Object target, Type type, String fieldName) { return withDefaultConfiguration().to(target, type, fieldName); }
Delegates any intercepted method to invoke a non-static method that is declared by the supplied type's instance or any of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • target – The target instance for the delegation.
  • type – The most specific type of which target should be considered. Must be a super type of the target's actual type.
  • fieldName – The name of the field that is holding the target instance.
  • methodGraphCompiler – The method graph compiler to use.
Returns:A method delegation that redirects method calls to a static method of the supplied type.
/** * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param target The target instance for the delegation. * @param type The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type. * @param fieldName The name of the field that is holding the {@code target} instance. * @param methodGraphCompiler The method graph compiler to use. * @return A method delegation that redirects method calls to a static method of the supplied type. */
public static MethodDelegation to(Object target, Type type, String fieldName, MethodGraph.Compiler methodGraphCompiler) { return withDefaultConfiguration().to(target, type, fieldName, methodGraphCompiler); }
Delegates any intercepted method to invoke a constructor of the supplied type. To be considered a valid delegation target, a constructor must be visible and accessible to the instrumented type. This is the case if the constructor's declaring type is either public or in the same package as the instrumented type and if the constructor is either public or non-private and in the same package as the instrumented type. Private constructors can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • type – The type to construct.
Returns:A delegation that redirects method calls to a constructor of the supplied type.
/** * Delegates any intercepted method to invoke a constructor of the supplied type. To be considered a valid delegation target, * a constructor must be visible and accessible to the instrumented type. This is the case if the constructor's declaring type is * either public or in the same package as the instrumented type and if the constructor is either public or non-private and in * the same package as the instrumented type. Private constructors can only be used as a delegation target if the delegation is * targeting the instrumented type. * * @param type The type to construct. * @return A delegation that redirects method calls to a constructor of the supplied type. */
public static MethodDelegation toConstructor(Class<?> type) { return withDefaultConfiguration().toConstructor(type); }
Delegates any intercepted method to invoke a constructor of the supplied type. To be considered a valid delegation target, a constructor must be visible and accessible to the instrumented type. This is the case if the constructor's declaring type is either public or in the same package as the instrumented type and if the constructor is either public or non-private and in the same package as the instrumented type. Private constructors can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • typeDescription – The type to construct.
Returns:A delegation that redirects method calls to a constructor of the supplied type.
/** * Delegates any intercepted method to invoke a constructor of the supplied type. To be considered a valid delegation target, * a constructor must be visible and accessible to the instrumented type. This is the case if the constructor's declaring type is * either public or in the same package as the instrumented type and if the constructor is either public or non-private and in * the same package as the instrumented type. Private constructors can only be used as a delegation target if the delegation is * targeting the instrumented type. * * @param typeDescription The type to construct. * @return A delegation that redirects method calls to a constructor of the supplied type. */
public static MethodDelegation toConstructor(TypeDescription typeDescription) { return withDefaultConfiguration().toConstructor(typeDescription); }
Delegates any intercepted method to invoke a non-static method on the instance of the supplied field. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • name – The field's name.
Returns:A delegation that redirects invocations to a method of the specified field's instance.
/** * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the * case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param name The field's name. * @return A delegation that redirects invocations to a method of the specified field's instance. */
public static MethodDelegation toField(String name) { return withDefaultConfiguration().toField(name); }
Delegates any intercepted method to invoke a non-static method on the instance of the supplied field. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • name – The field's name.
  • fieldLocatorFactory – The field locator factory to use.
Returns:A delegation that redirects invocations to a method of the specified field's instance.
/** * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the * case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param name The field's name. * @param fieldLocatorFactory The field locator factory to use. * @return A delegation that redirects invocations to a method of the specified field's instance. */
public static MethodDelegation toField(String name, FieldLocator.Factory fieldLocatorFactory) { return withDefaultConfiguration().toField(name, fieldLocatorFactory); }
Delegates any intercepted method to invoke a non-static method on the instance of the supplied field. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • name – The field's name.
  • methodGraphCompiler – The method graph compiler to use.
Returns:A delegation that redirects invocations to a method of the specified field's instance.
/** * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the * case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param name The field's name. * @param methodGraphCompiler The method graph compiler to use. * @return A delegation that redirects invocations to a method of the specified field's instance. */
public static MethodDelegation toField(String name, MethodGraph.Compiler methodGraphCompiler) { return withDefaultConfiguration().toField(name, methodGraphCompiler); }
Delegates any intercepted method to invoke a non-static method on the instance of the supplied field. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • name – The field's name.
  • fieldLocatorFactory – The field locator factory to use.
  • methodGraphCompiler – The method graph compiler to use.
Returns:A delegation that redirects invocations to a method of the specified field's instance.
/** * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the * case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param name The field's name. * @param fieldLocatorFactory The field locator factory to use. * @param methodGraphCompiler The method graph compiler to use. * @return A delegation that redirects invocations to a method of the specified field's instance. */
public static MethodDelegation toField(String name, FieldLocator.Factory fieldLocatorFactory, MethodGraph.Compiler methodGraphCompiler) { return withDefaultConfiguration().toField(name, fieldLocatorFactory, methodGraphCompiler); }
Delegates any intercepted method to invoke a method on an instance that is returned by a parameterless method of the given name. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • name – The name of the method that returns the delegation target.
Returns:A delegation that redirects invocations to the return value of a method that is declared by the instrumented type.
/** * Delegates any intercepted method to invoke a method on an instance that is returned by a parameterless method of the * given name. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if * the method is either public or non-private and in the same package as the instrumented type. Private methods can only * be used as a delegation target if the delegation is targeting the instrumented type. * * @param name The name of the method that returns the delegation target. * @return A delegation that redirects invocations to the return value of a method that is declared by the instrumented type. */
public static MethodDelegation toMethodReturnOf(String name) { return withDefaultConfiguration().toMethodReturnOf(name); }
Delegates any intercepted method to invoke a method on an instance that is returned by a parameterless method of the given name. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • name – The name of the method that returns the delegation target.
  • methodGraphCompiler – The method graph compiler to use.
Returns:A delegation that redirects invocations to the return value of a method that is declared by the instrumented type.
/** * Delegates any intercepted method to invoke a method on an instance that is returned by a parameterless method of the * given name. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if * the method is either public or non-private and in the same package as the instrumented type. Private methods can only * be used as a delegation target if the delegation is targeting the instrumented type. * * @param name The name of the method that returns the delegation target. * @param methodGraphCompiler The method graph compiler to use. * @return A delegation that redirects invocations to the return value of a method that is declared by the instrumented type. */
public static MethodDelegation toMethodReturnOf(String name, MethodGraph.Compiler methodGraphCompiler) { return withDefaultConfiguration().toMethodReturnOf(name, methodGraphCompiler); }
Creates a configuration builder for a method delegation that is pre-configured with the ambiguity resolvers defined by AmbiguityResolver.DEFAULT and the parameter binders defined by ParameterBinder.DEFAULTS.
Returns:A method delegation configuration with pre-configuration.
/** * Creates a configuration builder for a method delegation that is pre-configured with the ambiguity resolvers defined by * {@link net.bytebuddy.implementation.bind.MethodDelegationBinder.AmbiguityResolver#DEFAULT} and the parameter binders * defined by {@link net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder.ParameterBinder#DEFAULTS}. * * @return A method delegation configuration with pre-configuration. */
public static WithCustomProperties withDefaultConfiguration() { return new WithCustomProperties(MethodDelegationBinder.AmbiguityResolver.DEFAULT, TargetMethodAnnotationDrivenBinder.ParameterBinder.DEFAULTS); }
Creates a configuration builder for a method delegation that does not apply any pre-configured AmbiguityResolvers or ParameterBinders.
Returns:A method delegation configuration without any pre-configuration.
/** * Creates a configuration builder for a method delegation that does not apply any pre-configured * {@link net.bytebuddy.implementation.bind.MethodDelegationBinder.AmbiguityResolver}s or * {@link net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder.ParameterBinder}s. * * @return A method delegation configuration without any pre-configuration. */
public static WithCustomProperties withEmptyConfiguration() { return new WithCustomProperties(MethodDelegationBinder.AmbiguityResolver.NoOp.INSTANCE, Collections.<TargetMethodAnnotationDrivenBinder.ParameterBinder<?>>emptyList()); }
Applies an assigner to the method delegation that is used for assigning method return and parameter types.
Params:
  • assigner – The assigner to apply.
Returns:A method delegation implementation that makes use of the given designer.
/** * Applies an assigner to the method delegation that is used for assigning method return and parameter types. * * @param assigner The assigner to apply. * @return A method delegation implementation that makes use of the given designer. */
public Implementation.Composable withAssigner(Assigner assigner) { return new MethodDelegation(implementationDelegate, parameterBinders, ambiguityResolver, terminationHandler, bindingResolver, assigner); }
{@inheritDoc}
/** * {@inheritDoc} */
public Implementation andThen(Implementation implementation) { return new Compound(new MethodDelegation(implementationDelegate, parameterBinders, ambiguityResolver, MethodDelegationBinder.TerminationHandler.Default.DROPPING, bindingResolver, assigner), implementation); }
{@inheritDoc}
/** * {@inheritDoc} */
public Composable andThen(Composable implementation) { return new Compound.Composable(new MethodDelegation(implementationDelegate, parameterBinders, ambiguityResolver, MethodDelegationBinder.TerminationHandler.Default.DROPPING, bindingResolver, assigner), implementation); }
{@inheritDoc}
/** * {@inheritDoc} */
public InstrumentedType prepare(InstrumentedType instrumentedType) { return implementationDelegate.prepare(instrumentedType); }
{@inheritDoc}
/** * {@inheritDoc} */
public ByteCodeAppender appender(Target implementationTarget) { ImplementationDelegate.Compiled compiled = implementationDelegate.compile(implementationTarget.getInstrumentedType()); return new Appender(implementationTarget, new MethodDelegationBinder.Processor(compiled.getRecords(), ambiguityResolver, bindingResolver), terminationHandler, assigner, compiled); }
An implementation delegate is responsible for executing the actual method delegation and for resolving the target methods.
/** * An implementation delegate is responsible for executing the actual method delegation and for resolving the target methods. */
protected interface ImplementationDelegate extends InstrumentedType.Prepareable {
A name prefix for fields.
/** * A name prefix for fields. */
String FIELD_NAME_PREFIX = "delegate";
Compiles this implementation delegate.
Params:
  • instrumentedType – The instrumented type.
Returns:A compiled implementation delegate.
/** * Compiles this implementation delegate. * * @param instrumentedType The instrumented type. * @return A compiled implementation delegate. */
Compiled compile(TypeDescription instrumentedType);
A compiled implementation delegate.
/** * A compiled implementation delegate. */
interface Compiled {
Resolves a stack manipulation that prepares the delegation invocation.
Params:
  • instrumentedMethod – The instrumented method.
Returns:A stack manipulation that is applied prior to loading arguments and executing the method call.
/** * Resolves a stack manipulation that prepares the delegation invocation. * * @param instrumentedMethod The instrumented method. * @return A stack manipulation that is applied prior to loading arguments and executing the method call. */
StackManipulation prepare(MethodDescription instrumentedMethod);
Resolves an invoker to use for invoking the delegation target.
Returns:The method invoker to use.
/** * Resolves an invoker to use for invoking the delegation target. * * @return The method invoker to use. */
MethodDelegationBinder.MethodInvoker invoke();
Returns a list of binding records to consider for delegation.
Returns:A list of delegation binder records to consider.
/** * Returns a list of binding records to consider for delegation. * * @return A list of delegation binder records to consider. */
List<MethodDelegationBinder.Record> getRecords();
A compiled implementation delegate for invoking a static method.
/** * A compiled implementation delegate for invoking a static method. */
@HashCodeAndEqualsPlugin.Enhance class ForStaticCall implements Compiled {
The list of records to consider.
/** * The list of records to consider. */
private final List<MethodDelegationBinder.Record> records;
Creates a new compiled implementation delegate for a static method call.
Params:
  • records – The list of records to consider.
/** * Creates a new compiled implementation delegate for a static method call. * * @param records The list of records to consider. */
protected ForStaticCall(List<MethodDelegationBinder.Record> records) { this.records = records; }
{@inheritDoc}
/** * {@inheritDoc} */
public StackManipulation prepare(MethodDescription instrumentedMethod) { return StackManipulation.Trivial.INSTANCE; }
{@inheritDoc}
/** * {@inheritDoc} */
public MethodDelegationBinder.MethodInvoker invoke() { return MethodDelegationBinder.MethodInvoker.Simple.INSTANCE; }
{@inheritDoc}
/** * {@inheritDoc} */
public List<MethodDelegationBinder.Record> getRecords() { return records; } }
A compiled implementation delegate that invokes methods on a field.
/** * A compiled implementation delegate that invokes methods on a field. */
@HashCodeAndEqualsPlugin.Enhance class ForField implements Compiled {
The field to delegate to.
/** * The field to delegate to. */
private final FieldDescription fieldDescription;
The records to consider for delegation.
/** * The records to consider for delegation. */
private final List<MethodDelegationBinder.Record> records;
Creates a new compiled implementation delegate for a field delegation.
Params:
  • fieldDescription – The field to delegate to.
  • records – The records to consider for delegation.
/** * Creates a new compiled implementation delegate for a field delegation. * * @param fieldDescription The field to delegate to. * @param records The records to consider for delegation. */
protected ForField(FieldDescription fieldDescription, List<MethodDelegationBinder.Record> records) { this.fieldDescription = fieldDescription; this.records = records; }
{@inheritDoc}
/** * {@inheritDoc} */
public StackManipulation prepare(MethodDescription instrumentedMethod) { if (instrumentedMethod.isStatic() && !fieldDescription.isStatic()) { throw new IllegalStateException("Cannot read " + fieldDescription + " from " + instrumentedMethod); } return new StackManipulation.Compound(fieldDescription.isStatic() ? StackManipulation.Trivial.INSTANCE : MethodVariableAccess.loadThis(), FieldAccess.forField(fieldDescription).read()); }
{@inheritDoc}
/** * {@inheritDoc} */
public MethodDelegationBinder.MethodInvoker invoke() { return new MethodDelegationBinder.MethodInvoker.Virtual(fieldDescription.getType().asErasure()); }
{@inheritDoc}
/** * {@inheritDoc} */
public List<MethodDelegationBinder.Record> getRecords() { return records; } }
A compiled implementation delegate that invokes a method on an instance that is returned by another method.
/** * A compiled implementation delegate that invokes a method on an instance that is returned by another method. */
@HashCodeAndEqualsPlugin.Enhance class ForMethodReturn implements Compiled {
The method to call for result.
/** * The method to call for result. */
private final MethodDescription methodDescription;
The records to consider for delegation.
/** * The records to consider for delegation. */
private final List<MethodDelegationBinder.Record> records;
Creates a new compiled implementation delegate for a field delegation.
Params:
  • methodDescription – The method to call for result.
  • records – The records to consider for delegation.
/** * Creates a new compiled implementation delegate for a field delegation. * * @param methodDescription The method to call for result. * @param records The records to consider for delegation. */
protected ForMethodReturn(MethodDescription methodDescription, List<MethodDelegationBinder.Record> records) { this.methodDescription = methodDescription; this.records = records; }
{@inheritDoc}
/** * {@inheritDoc} */
public StackManipulation prepare(MethodDescription instrumentedMethod) { if (instrumentedMethod.isStatic() && !methodDescription.isStatic()) { throw new IllegalStateException("Cannot invoke " + methodDescription + " from " + instrumentedMethod); } return new StackManipulation.Compound(methodDescription.isStatic() ? StackManipulation.Trivial.INSTANCE : MethodVariableAccess.loadThis(), MethodInvocation.invoke(methodDescription)); }
{@inheritDoc}
/** * {@inheritDoc} */
public MethodDelegationBinder.MethodInvoker invoke() { return new MethodDelegationBinder.MethodInvoker.Virtual(methodDescription.getReturnType().asErasure()); }
{@inheritDoc}
/** * {@inheritDoc} */
public List<MethodDelegationBinder.Record> getRecords() { return records; } }
A compiled implementation delegate for a constructor delegation.
/** * A compiled implementation delegate for a constructor delegation. */
@HashCodeAndEqualsPlugin.Enhance class ForConstruction implements Compiled {
The type to be constructed.
/** * The type to be constructed. */
private final TypeDescription typeDescription;
The records to consider for delegation.
/** * The records to consider for delegation. */
private final List<MethodDelegationBinder.Record> records;
Creates a new compiled implementation delegate for a constructor delegation.
Params:
  • typeDescription – The type to be constructed.
  • records – The records to consider for delegation.
/** * Creates a new compiled implementation delegate for a constructor delegation. * * @param typeDescription The type to be constructed. * @param records The records to consider for delegation. */
protected ForConstruction(TypeDescription typeDescription, List<MethodDelegationBinder.Record> records) { this.typeDescription = typeDescription; this.records = records; }
{@inheritDoc}
/** * {@inheritDoc} */
public StackManipulation prepare(MethodDescription instrumentedMethod) { return new StackManipulation.Compound(TypeCreation.of(typeDescription), Duplication.SINGLE); }
{@inheritDoc}
/** * {@inheritDoc} */
public MethodDelegationBinder.MethodInvoker invoke() { return MethodDelegationBinder.MethodInvoker.Simple.INSTANCE; }
{@inheritDoc}
/** * {@inheritDoc} */
public List<MethodDelegationBinder.Record> getRecords() { return records; } } }
An implementation delegate for a static method delegation.
/** * An implementation delegate for a static method delegation. */
@HashCodeAndEqualsPlugin.Enhance class ForStaticMethod implements ImplementationDelegate {
The precompiled records.
/** * The precompiled records. */
private final List<MethodDelegationBinder.Record> records;
Creates a new implementation delegate for a static method delegation.
Params:
  • records – The precompiled record.
/** * Creates a new implementation delegate for a static method delegation. * * @param records The precompiled record. */
protected ForStaticMethod(List<MethodDelegationBinder.Record> records) { this.records = records; }
Precompiles a static method delegation for a given list of methods.
Params:
  • methods – The methods to consider.
  • methodDelegationBinder – The method delegation binder to use.
Returns:An appropriate implementation delegate.
/** * Precompiles a static method delegation for a given list of methods. * * @param methods The methods to consider. * @param methodDelegationBinder The method delegation binder to use. * @return An appropriate implementation delegate. */
protected static ImplementationDelegate of(MethodList<?> methods, MethodDelegationBinder methodDelegationBinder) { List<MethodDelegationBinder.Record> records = new ArrayList<MethodDelegationBinder.Record>(methods.size()); for (MethodDescription methodDescription : methods) { records.add(methodDelegationBinder.compile(methodDescription)); } return new ForStaticMethod(records); }
{@inheritDoc}
/** * {@inheritDoc} */
public InstrumentedType prepare(InstrumentedType instrumentedType) { return instrumentedType; }
{@inheritDoc}
/** * {@inheritDoc} */
public ImplementationDelegate.Compiled compile(TypeDescription instrumentedType) { return new Compiled.ForStaticCall(records); } }
An implementation delegate for invoking methods on a field that is declared by the instrumented type or a super type.
/** * An implementation delegate for invoking methods on a field that is declared by the instrumented type or a super type. */
@HashCodeAndEqualsPlugin.Enhance abstract class ForField implements ImplementationDelegate {
The name of the field that is target of the delegation.
/** * The name of the field that is target of the delegation. */
protected final String fieldName;
The method graph compiler to use.
/** * The method graph compiler to use. */
protected final MethodGraph.Compiler methodGraphCompiler;
The parameter binders to use.
/** * The parameter binders to use. */
protected final List<? extends TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders;
The matcher to use for filtering methods.
/** * The matcher to use for filtering methods. */
protected final ElementMatcher<? super MethodDescription> matcher;
Creates a new implementation delegate for a field delegation.
Params:
  • fieldName – The name of the field that is target of the delegation.
  • methodGraphCompiler – The method graph compiler to use.
  • parameterBinders – The parameter binders to use.
  • matcher – The matcher to use for filtering methods.
/** * Creates a new implementation delegate for a field delegation. * * @param fieldName The name of the field that is target of the delegation. * @param methodGraphCompiler The method graph compiler to use. * @param parameterBinders The parameter binders to use. * @param matcher The matcher to use for filtering methods. */
protected ForField(String fieldName, MethodGraph.Compiler methodGraphCompiler, List<? extends TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders, ElementMatcher<? super MethodDescription> matcher) { this.fieldName = fieldName; this.methodGraphCompiler = methodGraphCompiler; this.parameterBinders = parameterBinders; this.matcher = matcher; }
{@inheritDoc}
/** * {@inheritDoc} */
public Compiled compile(TypeDescription instrumentedType) { FieldDescription fieldDescription = resolve(instrumentedType); if (!fieldDescription.getType().asErasure().isVisibleTo(instrumentedType)) { throw new IllegalStateException(fieldDescription + " is not visible to " + instrumentedType); } else { MethodList<?> candidates = methodGraphCompiler.compile(fieldDescription.getType(), instrumentedType) .listNodes() .asMethodList() .filter(matcher); List<MethodDelegationBinder.Record> records = new ArrayList<MethodDelegationBinder.Record>(candidates.size()); MethodDelegationBinder methodDelegationBinder = TargetMethodAnnotationDrivenBinder.of(parameterBinders); for (MethodDescription candidate : candidates) { records.add(methodDelegationBinder.compile(candidate)); } return new Compiled.ForField(fieldDescription, records); } }
Resolves the field to which is delegated.
Params:
  • instrumentedType – The instrumented type.
Returns:The field that is the delegation target.
/** * Resolves the field to which is delegated. * * @param instrumentedType The instrumented type. * @return The field that is the delegation target. */
protected abstract FieldDescription resolve(TypeDescription instrumentedType);
An implementation target for a static field that is declared by the instrumented type and that is assigned an instance.
/** * An implementation target for a static field that is declared by the instrumented type and that is assigned an instance. */
@HashCodeAndEqualsPlugin.Enhance protected static class WithInstance extends ForField {
The target instance.
/** * The target instance. */
private final Object target;
The field's type.
/** * The field's type. */
private final TypeDescription.Generic fieldType;
Creates a new implementation delegate for invoking methods on a supplied instance.
Params:
  • fieldName – The name of the field that is target of the delegation.
  • methodGraphCompiler – The method graph compiler to use.
  • parameterBinders – The parameter binders to use.
  • matcher – The matcher to use for filtering methods.
  • target – The target instance.
  • fieldType – The field's type.
/** * Creates a new implementation delegate for invoking methods on a supplied instance. * * @param fieldName The name of the field that is target of the delegation. * @param methodGraphCompiler The method graph compiler to use. * @param parameterBinders The parameter binders to use. * @param matcher The matcher to use for filtering methods. * @param target The target instance. * @param fieldType The field's type. */
protected WithInstance(String fieldName, MethodGraph.Compiler methodGraphCompiler, List<? extends TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders, ElementMatcher<? super MethodDescription> matcher, Object target, TypeDescription.Generic fieldType) { super(fieldName, methodGraphCompiler, parameterBinders, matcher); this.target = target; this.fieldType = fieldType; }
{@inheritDoc}
/** * {@inheritDoc} */
public InstrumentedType prepare(InstrumentedType instrumentedType) { return instrumentedType .withField(new FieldDescription.Token(fieldName, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_VOLATILE | Opcodes.ACC_SYNTHETIC, fieldType)) .withInitializer(new LoadedTypeInitializer.ForStaticField(fieldName, target)); } @Override protected FieldDescription resolve(TypeDescription instrumentedType) { if (!fieldType.asErasure().isVisibleTo(instrumentedType)) { throw new IllegalStateException(fieldType + " is not visible to " + instrumentedType); } else { return instrumentedType.getDeclaredFields() .filter(named(fieldName).and(fieldType(fieldType.asErasure()))) .getOnly(); } } }
An implementation target for a field that is declared by the instrumented type or a super type.
/** * An implementation target for a field that is declared by the instrumented type or a super type. */
@HashCodeAndEqualsPlugin.Enhance protected static class WithLookup extends ForField {
The field locator factory to use for locating the field to delegate to.
/** * The field locator factory to use for locating the field to delegate to. */
private final FieldLocator.Factory fieldLocatorFactory;
Creates a new implementation delegate for a field that is declared by the instrumented type or any super type.
Params:
  • fieldName – The name of the field that is target of the delegation.
  • methodGraphCompiler – The method graph compiler to use.
  • parameterBinders – The parameter binders to use.
  • matcher – The matcher to use for filtering methods.
  • fieldLocatorFactory – The field locator factory to use for locating the field to delegate to.
/** * Creates a new implementation delegate for a field that is declared by the instrumented type or any super type. * * @param fieldName The name of the field that is target of the delegation. * @param methodGraphCompiler The method graph compiler to use. * @param parameterBinders The parameter binders to use. * @param matcher The matcher to use for filtering methods. * @param fieldLocatorFactory The field locator factory to use for locating the field to delegate to. */
protected WithLookup(String fieldName, MethodGraph.Compiler methodGraphCompiler, List<? extends TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders, ElementMatcher<? super MethodDescription> matcher, FieldLocator.Factory fieldLocatorFactory) { super(fieldName, methodGraphCompiler, parameterBinders, matcher); this.fieldLocatorFactory = fieldLocatorFactory; }
{@inheritDoc}
/** * {@inheritDoc} */
public InstrumentedType prepare(InstrumentedType instrumentedType) { return instrumentedType; } @Override protected FieldDescription resolve(TypeDescription instrumentedType) { FieldLocator.Resolution resolution = fieldLocatorFactory.make(instrumentedType).locate(fieldName); if (!resolution.isResolved()) { throw new IllegalStateException("Could not locate " + fieldName + " on " + instrumentedType); } else { return resolution.getField(); } } } }
An implementation delegate for invoking a delegation target on the another methods return value.
/** * An implementation delegate for invoking a delegation target on the another methods return value. */
@HashCodeAndEqualsPlugin.Enhance class ForMethodReturn implements ImplementationDelegate {
The name of the method to invoke.
/** * The name of the method to invoke. */
private final String name;
The method graph compiler to use.
/** * The method graph compiler to use. */
private final MethodGraph.Compiler methodGraphCompiler;
The parameter binders to use.
/** * The parameter binders to use. */
private final List<? extends TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders;
The matcher to use for filtering methods.
/** * The matcher to use for filtering methods. */
private final ElementMatcher<? super MethodDescription> matcher;
Creates a new implementation delegate for a method return value delegation.
Params:
  • name – The name of the method to invoke.
  • methodGraphCompiler – The method graph compiler to use.
  • parameterBinders – The parameter binders to use.
  • matcher – The matcher to use for filtering methods.
/** * Creates a new implementation delegate for a method return value delegation. * * @param name The name of the method to invoke. * @param methodGraphCompiler The method graph compiler to use. * @param parameterBinders The parameter binders to use. * @param matcher The matcher to use for filtering methods. */
protected ForMethodReturn(String name, MethodGraph.Compiler methodGraphCompiler, List<? extends TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders, ElementMatcher<? super MethodDescription> matcher) { this.name = name; this.methodGraphCompiler = methodGraphCompiler; this.parameterBinders = parameterBinders; this.matcher = matcher; }
{@inheritDoc}
/** * {@inheritDoc} */
public Compiled compile(TypeDescription instrumentedType) { MethodList<?> targets = new MethodList.Explicit<MethodDescription>(CompoundList.<MethodDescription>of( instrumentedType.getDeclaredMethods().filter(isStatic().or(isPrivate())), methodGraphCompiler.compile(instrumentedType).listNodes().asMethodList()) ).filter(named(name).and(takesArguments(0)).and(not(returns(isPrimitive().or(isArray()))))); if (targets.size() != 1) { throw new IllegalStateException(instrumentedType + " does not define method without arguments with name " + name + ": " + targets); } else if (!targets.getOnly().getReturnType().asErasure().isVisibleTo(instrumentedType)) { throw new IllegalStateException(targets.getOnly() + " is not visible to " + instrumentedType); } else { MethodList<?> candidates = methodGraphCompiler.compile(targets.getOnly().getReturnType(), instrumentedType) .listNodes() .asMethodList() .filter(matcher); List<MethodDelegationBinder.Record> records = new ArrayList<MethodDelegationBinder.Record>(candidates.size()); MethodDelegationBinder methodDelegationBinder = TargetMethodAnnotationDrivenBinder.of(parameterBinders); for (MethodDescription candidate : candidates) { records.add(methodDelegationBinder.compile(candidate)); } return new Compiled.ForMethodReturn(targets.get(0), records); } }
{@inheritDoc}
/** * {@inheritDoc} */
public InstrumentedType prepare(InstrumentedType instrumentedType) { return instrumentedType; } }
An implementation delegate for constructing an instance.
/** * An implementation delegate for constructing an instance. */
@HashCodeAndEqualsPlugin.Enhance class ForConstruction implements ImplementationDelegate {
The type being constructed.
/** * The type being constructed. */
private final TypeDescription typeDescription;
The precompiled delegation records.
/** * The precompiled delegation records. */
private final List<MethodDelegationBinder.Record> records;
Creates an implementation delegate for constructing a new instance.
Params:
  • typeDescription – The type being constructed.
  • records – The precompiled delegation records.
/** * Creates an implementation delegate for constructing a new instance. * * @param typeDescription The type being constructed. * @param records The precompiled delegation records. */
protected ForConstruction(TypeDescription typeDescription, List<MethodDelegationBinder.Record> records) { this.typeDescription = typeDescription; this.records = records; }
Creates an implementation delegate for constructing a new instance.
Params:
  • typeDescription – The type being constructed.
  • methods – The constructors to consider.
  • methodDelegationBinder – The method delegation binder to use.
Returns:An appropriate implementation delegate.
/** * Creates an implementation delegate for constructing a new instance. * * @param typeDescription The type being constructed. * @param methods The constructors to consider. * @param methodDelegationBinder The method delegation binder to use. * @return An appropriate implementation delegate. */
protected static ImplementationDelegate of(TypeDescription typeDescription, MethodList<?> methods, MethodDelegationBinder methodDelegationBinder) { List<MethodDelegationBinder.Record> records = new ArrayList<MethodDelegationBinder.Record>(methods.size()); for (MethodDescription methodDescription : methods) { records.add(methodDelegationBinder.compile(methodDescription)); } return new ForConstruction(typeDescription, records); }
{@inheritDoc}
/** * {@inheritDoc} */
public InstrumentedType prepare(InstrumentedType instrumentedType) { return instrumentedType; }
{@inheritDoc}
/** * {@inheritDoc} */
public Compiled compile(TypeDescription instrumentedType) { return new Compiled.ForConstruction(typeDescription, records); } } }
The appender for implementing a MethodDelegation.
/** * The appender for implementing a {@link net.bytebuddy.implementation.MethodDelegation}. */
@HashCodeAndEqualsPlugin.Enhance protected static class Appender implements ByteCodeAppender {
The implementation target of this implementation.
/** * The implementation target of this implementation. */
private final Target implementationTarget;
The method delegation binder processor which is responsible for implementing the method delegation.
/** * The method delegation binder processor which is responsible for implementing the method delegation. */
private final MethodDelegationBinder.Record processor;
A termination handler for a method delegation binder.
/** * A termination handler for a method delegation binder. */
private final MethodDelegationBinder.TerminationHandler terminationHandler;
The assigner to use.
/** * The assigner to use. */
private final Assigner assigner;
The compiled implementation delegate.
/** * The compiled implementation delegate. */
private final ImplementationDelegate.Compiled compiled;
Creates a new appender for a method delegation.
Params:
  • implementationTarget – The implementation target of this implementation.
  • processor – The method delegation binder processor which is responsible for implementing the method delegation.
  • terminationHandler – A termination handler for a method delegation binder.
  • assigner – The assigner to use.
  • compiled – The compiled implementation delegate.
/** * Creates a new appender for a method delegation. * * @param implementationTarget The implementation target of this implementation. * @param processor The method delegation binder processor which is responsible for implementing the method delegation. * @param terminationHandler A termination handler for a method delegation binder. * @param assigner The assigner to use. * @param compiled The compiled implementation delegate. */
protected Appender(Target implementationTarget, MethodDelegationBinder.Record processor, MethodDelegationBinder.TerminationHandler terminationHandler, Assigner assigner, ImplementationDelegate.Compiled compiled) { this.implementationTarget = implementationTarget; this.processor = processor; this.terminationHandler = terminationHandler; this.assigner = assigner; this.compiled = compiled; }
{@inheritDoc}
/** * {@inheritDoc} */
public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) { StackManipulation.Size stackSize = new StackManipulation.Compound( compiled.prepare(instrumentedMethod), processor.bind(implementationTarget, instrumentedMethod, terminationHandler, compiled.invoke(), assigner) ).apply(methodVisitor, implementationContext); return new Size(stackSize.getMaximalSize(), instrumentedMethod.getStackSize()); } }
A MethodDelegation with custom configuration.
/** * A {@link MethodDelegation} with custom configuration. */
@HashCodeAndEqualsPlugin.Enhance public static class WithCustomProperties {
The ambiguity resolver to use.
/** * The ambiguity resolver to use. */
private final MethodDelegationBinder.AmbiguityResolver ambiguityResolver;
The parameter binders to use.
/** * The parameter binders to use. */
private final List<TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders;
The binding resolver being used to select the relevant method binding.
/** * The binding resolver being used to select the relevant method binding. */
private final MethodDelegationBinder.BindingResolver bindingResolver;
The matcher to use for filtering relevant methods.
/** * The matcher to use for filtering relevant methods. */
private final ElementMatcher<? super MethodDescription> matcher;
Creates a new method delegation with custom properties that does not filter any methods.
Params:
  • ambiguityResolver – The ambiguity resolver to use.
  • parameterBinders – The parameter binders to use.
/** * Creates a new method delegation with custom properties that does not filter any methods. * * @param ambiguityResolver The ambiguity resolver to use. * @param parameterBinders The parameter binders to use. */
protected WithCustomProperties(MethodDelegationBinder.AmbiguityResolver ambiguityResolver, List<TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders) { this(ambiguityResolver, parameterBinders, MethodDelegationBinder.BindingResolver.Default.INSTANCE, any()); }
Creates a new method delegation with custom properties.
Params:
  • ambiguityResolver – The ambiguity resolver to use.
  • parameterBinders – The parameter binders to use.
  • bindingResolver – The binding resolver being used to select the relevant method binding.
  • matcher – The matcher to use for filtering relevant methods.
/** * Creates a new method delegation with custom properties. * * @param ambiguityResolver The ambiguity resolver to use. * @param parameterBinders The parameter binders to use. * @param bindingResolver The binding resolver being used to select the relevant method binding. * @param matcher The matcher to use for filtering relevant methods. */
private WithCustomProperties(MethodDelegationBinder.AmbiguityResolver ambiguityResolver, List<TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders, MethodDelegationBinder.BindingResolver bindingResolver, ElementMatcher<? super MethodDescription> matcher) { this.ambiguityResolver = ambiguityResolver; this.parameterBinders = parameterBinders; this.bindingResolver = bindingResolver; this.matcher = matcher; }
Configures this method delegation to use the supplied ambiguity resolvers when deciding which out of two ore more legal delegation targets should be considered.
Params:
  • ambiguityResolver – The ambiguity resolvers to use in their application order.
Returns:A new delegation configuration which also applies the supplied ambiguity resolvers.
/** * Configures this method delegation to use the supplied ambiguity resolvers when deciding which out of two ore * more legal delegation targets should be considered. * * @param ambiguityResolver The ambiguity resolvers to use in their application order. * @return A new delegation configuration which also applies the supplied ambiguity resolvers. */
public WithCustomProperties withResolvers(MethodDelegationBinder.AmbiguityResolver... ambiguityResolver) { return withResolvers(Arrays.asList(ambiguityResolver)); }
Configures this method delegation to use the supplied ambiguity resolvers when deciding which out of two ore more legal delegation targets should be considered.
Params:
  • ambiguityResolvers – The ambiguity resolvers to use in their application order.
Returns:A new delegation configuration which also applies the supplied ambiguity resolvers.
/** * Configures this method delegation to use the supplied ambiguity resolvers when deciding which out of two ore * more legal delegation targets should be considered. * * @param ambiguityResolvers The ambiguity resolvers to use in their application order. * @return A new delegation configuration which also applies the supplied ambiguity resolvers. */
public WithCustomProperties withResolvers(List<? extends MethodDelegationBinder.AmbiguityResolver> ambiguityResolvers) { return new WithCustomProperties(new MethodDelegationBinder.AmbiguityResolver.Compound(CompoundList.of(this.ambiguityResolver, ambiguityResolvers)), parameterBinders, bindingResolver, matcher); }
Configures this method delegation to use the supplied parameter binders when deciding what value to assign to a parameter of a delegation target.
Params:
  • parameterBinder – The parameter binders to use.
Returns:A new delegation configuration which also applies the supplied parameter binders.
/** * Configures this method delegation to use the supplied parameter binders when deciding what value to assign to * a parameter of a delegation target. * * @param parameterBinder The parameter binders to use. * @return A new delegation configuration which also applies the supplied parameter binders. */
public WithCustomProperties withBinders(TargetMethodAnnotationDrivenBinder.ParameterBinder<?>... parameterBinder) { return withBinders(Arrays.asList(parameterBinder)); }
Configures this method delegation to use the supplied parameter binders when deciding what value to assign to a parameter of a delegation target.
Params:
  • parameterBinders – The parameter binders to use.
Returns:A new delegation configuration which also applies the supplied parameter binders.
/** * Configures this method delegation to use the supplied parameter binders when deciding what value to assign to * a parameter of a delegation target. * * @param parameterBinders The parameter binders to use. * @return A new delegation configuration which also applies the supplied parameter binders. */
public WithCustomProperties withBinders(List<? extends TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders) { return new WithCustomProperties(ambiguityResolver, CompoundList.of(this.parameterBinders, parameterBinders), bindingResolver, matcher); }
Configures a custom binding resolver which is responsible for choosing a method binding among multiple candidates. Configuring a resolver overrides any previous configuration.
Params:
  • bindingResolver – The binding resolver being used to select the relevant method binding.
Returns:A new delegation configuration which applies the supplied binding resolver.
/** * Configures a custom binding resolver which is responsible for choosing a method binding among multiple candidates. Configuring * a resolver overrides any previous configuration. * * @param bindingResolver The binding resolver being used to select the relevant method binding. * @return A new delegation configuration which applies the supplied binding resolver. */
public WithCustomProperties withBindingResolver(MethodDelegationBinder.BindingResolver bindingResolver) { return new WithCustomProperties(ambiguityResolver, parameterBinders, bindingResolver, matcher); }
Configures this method delegation to only consider methods or constructors as a delegation target if they match the supplied matcher.
Params:
  • matcher – The matcher any delegation target needs to match in order to be considered a for delegation.
Returns:A new delegation configuration which only considers methods for delegation if they match the supplied matcher.
/** * Configures this method delegation to only consider methods or constructors as a delegation target if they match the supplied matcher. * * @param matcher The matcher any delegation target needs to match in order to be considered a for delegation. * @return A new delegation configuration which only considers methods for delegation if they match the supplied matcher. */
public WithCustomProperties filter(ElementMatcher<? super MethodDescription> matcher) { return new WithCustomProperties(ambiguityResolver, parameterBinders, bindingResolver, new ElementMatcher.Junction.Conjunction<MethodDescription>(this.matcher, matcher)); }
Delegates any intercepted method to invoke a static method that is declared by the supplied type. To be considered a valid delegation target, the target method must be visible and accessible to the instrumented type. This is the case if the target type is either public or in the same package as the instrumented type and if the target method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the interception is targeting the instrumented type.
Params:
  • type – The target type for the delegation.
Returns:A method delegation that redirects method calls to a static method of the supplied type.
/** * Delegates any intercepted method to invoke a {@code static} method that is declared by the supplied type. To be considered * a valid delegation target, the target method must be visible and accessible to the instrumented type. This is the case if * the target type is either public or in the same package as the instrumented type and if the target method is either public * or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if * the interception is targeting the instrumented type. * * @param type The target type for the delegation. * @return A method delegation that redirects method calls to a static method of the supplied type. */
public MethodDelegation to(Class<?> type) { return to(TypeDescription.ForLoadedType.of(type)); }
Delegates any intercepted method to invoke a static method that is declared by the supplied type. To be considered a valid delegation target, the target method must be visible and accessible to the instrumented type. This is the case if the target type is either public or in the same package as the instrumented type and if the target method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • typeDescription – The target type for the delegation.
Returns:A method delegation that redirects method calls to a static method of the supplied type.
/** * Delegates any intercepted method to invoke a {@code static} method that is declared by the supplied type. To be considered * a valid delegation target, the target method must be visible and accessible to the instrumented type. This is the case if * the target type is either public or in the same package as the instrumented type and if the target method is either public * or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if * the delegation is targeting the instrumented type. * * @param typeDescription The target type for the delegation. * @return A method delegation that redirects method calls to a static method of the supplied type. */
public MethodDelegation to(TypeDescription typeDescription) { if (typeDescription.isArray()) { throw new IllegalArgumentException("Cannot delegate to array " + typeDescription); } else if (typeDescription.isPrimitive()) { throw new IllegalArgumentException("Cannot delegate to primitive " + typeDescription); } return new MethodDelegation(ImplementationDelegate.ForStaticMethod.of(typeDescription.getDeclaredMethods().filter(isStatic().and(matcher)), TargetMethodAnnotationDrivenBinder.of(parameterBinders)), parameterBinders, ambiguityResolver, bindingResolver); }
Delegates any intercepted method to invoke a non-static method that is declared by the supplied type's instance or any of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • target – The target instance for the delegation.
Returns:A method delegation that redirects method calls to a static method of the supplied type.
/** * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param target The target instance for the delegation. * @return A method delegation that redirects method calls to a static method of the supplied type. */
public MethodDelegation to(Object target) { return to(target, MethodGraph.Compiler.DEFAULT); }
Delegates any intercepted method to invoke a non-static method that is declared by the supplied type's instance or any of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • target – The target instance for the delegation.
  • methodGraphCompiler – The method graph compiler to use.
Returns:A method delegation that redirects method calls to a static method of the supplied type.
/** * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param target The target instance for the delegation. * @param methodGraphCompiler The method graph compiler to use. * @return A method delegation that redirects method calls to a static method of the supplied type. */
public MethodDelegation to(Object target, MethodGraph.Compiler methodGraphCompiler) { return to(target, target.getClass(), methodGraphCompiler); }
Delegates any intercepted method to invoke a non-static method that is declared by the supplied type's instance or any of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • target – The target instance for the delegation.
  • fieldName – The name of the field that is holding the target instance.
Returns:A method delegation that redirects method calls to a static method of the supplied type.
/** * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param target The target instance for the delegation. * @param fieldName The name of the field that is holding the {@code target} instance. * @return A method delegation that redirects method calls to a static method of the supplied type. */
public MethodDelegation to(Object target, String fieldName) { return to(target, fieldName, MethodGraph.Compiler.DEFAULT); }
Delegates any intercepted method to invoke a non-static method that is declared by the supplied type's instance or any of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • target – The target instance for the delegation.
  • fieldName – The name of the field that is holding the target instance.
  • methodGraphCompiler – The method graph compiler to use.
Returns:A method delegation that redirects method calls to a static method of the supplied type.
/** * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param target The target instance for the delegation. * @param fieldName The name of the field that is holding the {@code target} instance. * @param methodGraphCompiler The method graph compiler to use. * @return A method delegation that redirects method calls to a static method of the supplied type. */
public MethodDelegation to(Object target, String fieldName, MethodGraph.Compiler methodGraphCompiler) { return to(target, target.getClass(), fieldName, methodGraphCompiler); }
Delegates any intercepted method to invoke a non-static method that is declared by the supplied type's instance or any of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • target – The target instance for the delegation.
  • type – The most specific type of which target should be considered. Must be a super type of the target's actual type.
Returns:A method delegation that redirects method calls to a static method of the supplied type.
/** * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param target The target instance for the delegation. * @param type The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type. * @return A method delegation that redirects method calls to a static method of the supplied type. */
public MethodDelegation to(Object target, Type type) { return to(target, type, MethodGraph.Compiler.DEFAULT); }
Delegates any intercepted method to invoke a non-static method that is declared by the supplied type's instance or any of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • target – The target instance for the delegation.
  • type – The most specific type of which target should be considered. Must be a super type of the target's actual type.
  • methodGraphCompiler – The method graph compiler to use.
Returns:A method delegation that redirects method calls to a static method of the supplied type.
/** * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param target The target instance for the delegation. * @param type The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type. * @param methodGraphCompiler The method graph compiler to use. * @return A method delegation that redirects method calls to a static method of the supplied type. */
public MethodDelegation to(Object target, Type type, MethodGraph.Compiler methodGraphCompiler) { return to(target, type, ImplementationDelegate.FIELD_NAME_PREFIX + "$" + RandomString.hashOf(target.hashCode()), methodGraphCompiler); }
Delegates any intercepted method to invoke a non-static method that is declared by the supplied type's instance or any of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • target – The target instance for the delegation.
  • type – The most specific type of which target should be considered. Must be a super type of the target's actual type.
  • fieldName – The name of the field that is holding the target instance.
Returns:A method delegation that redirects method calls to a static method of the supplied type.
/** * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param target The target instance for the delegation. * @param type The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type. * @param fieldName The name of the field that is holding the {@code target} instance. * @return A method delegation that redirects method calls to a static method of the supplied type. */
public MethodDelegation to(Object target, Type type, String fieldName) { return to(target, type, fieldName, MethodGraph.Compiler.DEFAULT); }
Delegates any intercepted method to invoke a non-static method that is declared by the supplied type's instance or any of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • target – The target instance for the delegation.
  • type – The most specific type of which target should be considered. Must be a super type of the target's actual type.
  • fieldName – The name of the field that is holding the target instance.
  • methodGraphCompiler – The method graph compiler to use.
Returns:A method delegation that redirects method calls to a static method of the supplied type.
/** * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param target The target instance for the delegation. * @param type The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type. * @param fieldName The name of the field that is holding the {@code target} instance. * @param methodGraphCompiler The method graph compiler to use. * @return A method delegation that redirects method calls to a static method of the supplied type. */
public MethodDelegation to(Object target, Type type, String fieldName, MethodGraph.Compiler methodGraphCompiler) { TypeDescription.Generic typeDescription = TypeDefinition.Sort.describe(type); if (!typeDescription.asErasure().isInstance(target)) { throw new IllegalArgumentException(target + " is not an instance of " + type); } return new MethodDelegation(new ImplementationDelegate.ForField.WithInstance(fieldName, methodGraphCompiler, parameterBinders, matcher, target, typeDescription), parameterBinders, ambiguityResolver, bindingResolver); }
Delegates any intercepted method to invoke a constructor of the supplied type. To be considered a valid delegation target, a constructor must be visible and accessible to the instrumented type. This is the case if the constructor's declaring type is either public or in the same package as the instrumented type and if the constructor is either public or non-private and in the same package as the instrumented type. Private constructors can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • type – The type to construct.
Returns:A delegation that redirects method calls to a constructor of the supplied type.
/** * Delegates any intercepted method to invoke a constructor of the supplied type. To be considered a valid delegation target, * a constructor must be visible and accessible to the instrumented type. This is the case if the constructor's declaring type is * either public or in the same package as the instrumented type and if the constructor is either public or non-private and in * the same package as the instrumented type. Private constructors can only be used as a delegation target if the delegation is * targeting the instrumented type. * * @param type The type to construct. * @return A delegation that redirects method calls to a constructor of the supplied type. */
public MethodDelegation toConstructor(Class<?> type) { return toConstructor(TypeDescription.ForLoadedType.of(type)); }
Delegates any intercepted method to invoke a constructor of the supplied type. To be considered a valid delegation target, a constructor must be visible and accessible to the instrumented type. This is the case if the constructor's declaring type is either public or in the same package as the instrumented type and if the constructor is either public or non-private and in the same package as the instrumented type. Private constructors can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • typeDescription – The type to construct.
Returns:A delegation that redirects method calls to a constructor of the supplied type.
/** * Delegates any intercepted method to invoke a constructor of the supplied type. To be considered a valid delegation target, * a constructor must be visible and accessible to the instrumented type. This is the case if the constructor's declaring type is * either public or in the same package as the instrumented type and if the constructor is either public or non-private and in * the same package as the instrumented type. Private constructors can only be used as a delegation target if the delegation is * targeting the instrumented type. * * @param typeDescription The type to construct. * @return A delegation that redirects method calls to a constructor of the supplied type. */
public MethodDelegation toConstructor(TypeDescription typeDescription) { return new MethodDelegation(ImplementationDelegate.ForConstruction.of(typeDescription, typeDescription.getDeclaredMethods().filter(isConstructor().and(matcher)), TargetMethodAnnotationDrivenBinder.of(parameterBinders)), parameterBinders, ambiguityResolver, bindingResolver); }
Delegates any intercepted method to invoke a non-static method on the instance of the supplied field. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • name – The field's name.
Returns:A delegation that redirects invocations to a method of the specified field's instance.
/** * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the * case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param name The field's name. * @return A delegation that redirects invocations to a method of the specified field's instance. */
public MethodDelegation toField(String name) { return toField(name, FieldLocator.ForClassHierarchy.Factory.INSTANCE); }
Delegates any intercepted method to invoke a non-static method on the instance of the supplied field. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • name – The field's name.
  • fieldLocatorFactory – The field locator factory to use.
Returns:A delegation that redirects invocations to a method of the specified field's instance.
/** * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the * case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param name The field's name. * @param fieldLocatorFactory The field locator factory to use. * @return A delegation that redirects invocations to a method of the specified field's instance. */
public MethodDelegation toField(String name, FieldLocator.Factory fieldLocatorFactory) { return toField(name, fieldLocatorFactory, MethodGraph.Compiler.DEFAULT); }
Delegates any intercepted method to invoke a non-static method on the instance of the supplied field. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • name – The field's name.
  • methodGraphCompiler – The method graph compiler to use.
Returns:A delegation that redirects invocations to a method of the specified field's instance.
/** * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the * case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param name The field's name. * @param methodGraphCompiler The method graph compiler to use. * @return A delegation that redirects invocations to a method of the specified field's instance. */
public MethodDelegation toField(String name, MethodGraph.Compiler methodGraphCompiler) { return toField(name, FieldLocator.ForClassHierarchy.Factory.INSTANCE, methodGraphCompiler); }
Delegates any intercepted method to invoke a non-static method on the instance of the supplied field. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • name – The field's name.
  • fieldLocatorFactory – The field locator factory to use.
  • methodGraphCompiler – The method graph compiler to use.
Returns:A delegation that redirects invocations to a method of the specified field's instance.
/** * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the * case if the method's declaring type is either public or in the same package as the instrumented type and if the method * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as * a delegation target if the delegation is targeting the instrumented type. * * @param name The field's name. * @param fieldLocatorFactory The field locator factory to use. * @param methodGraphCompiler The method graph compiler to use. * @return A delegation that redirects invocations to a method of the specified field's instance. */
public MethodDelegation toField(String name, FieldLocator.Factory fieldLocatorFactory, MethodGraph.Compiler methodGraphCompiler) { return new MethodDelegation(new ImplementationDelegate.ForField.WithLookup(name, methodGraphCompiler, parameterBinders, matcher, fieldLocatorFactory), parameterBinders, ambiguityResolver, bindingResolver); }
Delegates any intercepted method to invoke a method on an instance that is returned by a parameterless method of the given name. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • name – The name of the method that returns the delegation target.
Returns:A delegation that redirects invocations to the return value of a method that is declared by the instrumented type.
/** * Delegates any intercepted method to invoke a method on an instance that is returned by a parameterless method of the * given name. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if * the method is either public or non-private and in the same package as the instrumented type. Private methods can only * be used as a delegation target if the delegation is targeting the instrumented type. * * @param name The name of the method that returns the delegation target. * @return A delegation that redirects invocations to the return value of a method that is declared by the instrumented type. */
public MethodDelegation toMethodReturnOf(String name) { return toMethodReturnOf(name, MethodGraph.Compiler.DEFAULT); }
Delegates any intercepted method to invoke a method on an instance that is returned by a parameterless method of the given name. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method is either public or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if the delegation is targeting the instrumented type.
Params:
  • name – The name of the method that returns the delegation target.
  • methodGraphCompiler – The method graph compiler to use.
Returns:A delegation that redirects invocations to the return value of a method that is declared by the instrumented type.
/** * Delegates any intercepted method to invoke a method on an instance that is returned by a parameterless method of the * given name. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type. * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if * the method is either public or non-private and in the same package as the instrumented type. Private methods can only * be used as a delegation target if the delegation is targeting the instrumented type. * * @param name The name of the method that returns the delegation target. * @param methodGraphCompiler The method graph compiler to use. * @return A delegation that redirects invocations to the return value of a method that is declared by the instrumented type. */
public MethodDelegation toMethodReturnOf(String name, MethodGraph.Compiler methodGraphCompiler) { return new MethodDelegation(new ImplementationDelegate.ForMethodReturn(name, methodGraphCompiler, parameterBinders, matcher), parameterBinders, ambiguityResolver, bindingResolver); } } }