All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.bytebuddy.ByteBuddy Maven / Gradle / Ivy

Go to download

Byte Buddy is a Java library for creating Java classes at run time. This artifact is a build of Byte Buddy with all ASM dependencies repackaged into its own name space.

There is a newer version: 1.15.11
Show newest version
package net.bytebuddy;

import net.bytebuddy.asm.ClassVisitorWrapper;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.scaffold.BridgeMethodResolver;
import net.bytebuddy.dynamic.scaffold.FieldRegistry;
import net.bytebuddy.dynamic.scaffold.MethodRegistry;
import net.bytebuddy.dynamic.scaffold.inline.ClassFileLocator;
import net.bytebuddy.dynamic.scaffold.inline.InlineDynamicTypeBuilder;
import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy;
import net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder;
import net.bytebuddy.instrumentation.Instrumentation;
import net.bytebuddy.instrumentation.ModifierContributor;
import net.bytebuddy.instrumentation.attribute.FieldAttributeAppender;
import net.bytebuddy.instrumentation.attribute.MethodAttributeAppender;
import net.bytebuddy.instrumentation.attribute.TypeAttributeAppender;
import net.bytebuddy.instrumentation.method.MethodLookupEngine;
import net.bytebuddy.instrumentation.method.matcher.MethodMatcher;
import net.bytebuddy.instrumentation.type.TypeDescription;
import net.bytebuddy.instrumentation.type.TypeList;
import net.bytebuddy.modifier.TypeManifestation;

import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static net.bytebuddy.instrumentation.method.matcher.MethodMatchers.*;
import static net.bytebuddy.utility.ByteBuddyCommons.*;

/**
 * {@code ByteBuddy} instances are configurable factories for creating new Java types at a JVM's runtime.
 * Such types are represented by {@link net.bytebuddy.dynamic.DynamicType}s which can be saved to disk or loaded into
 * the Java virtual machine. Each instance of {@code ByteBuddy} is immutable where any of the factory methods returns
 * a new instance that represents the altered configuration.
 * 

 

* Note that any configuration defines to ignore the instrumentation of any synthetic methods or the default finalizer * method {@link Object#finalize()}. This behavior can be altered by * {@link net.bytebuddy.ByteBuddy#withIgnoredMethods(net.bytebuddy.instrumentation.method.matcher.MethodMatcher)}. */ public class ByteBuddy { /** * The default prefix for the default {@link net.bytebuddy.NamingStrategy}. */ private static final String BYTE_BUDDY_DEFAULT_PREFIX = "ByteBuddy"; /** * The class file version of the current configuration. */ protected final ClassFileVersion classFileVersion; /** * The naming strategy of the current configuration. */ protected final NamingStrategy namingStrategy; /** * A list of interface types to be implemented by any class that is implemented by the current configuration. */ protected final List interfaceTypes; /** * A matcher for identifying methods that should never be intercepted. */ protected final MethodMatcher ignoredMethods; /** * The factory for generating a bridge method resolver for the current configuration. */ protected final BridgeMethodResolver.Factory bridgeMethodResolverFactory; /** * The class visitor wrapper chain for the current configuration. */ protected final ClassVisitorWrapper.Chain classVisitorWrapperChain; /** * The method registry for the current configuration. */ protected final MethodRegistry methodRegistry; /** * The modifiers to apply to any type that is generated by this configuration. */ protected final Definable modifiers; /** * The method lookup engine factory to apply to any type that is generated by this configuration. */ protected final MethodLookupEngine.Factory methodLookupEngineFactory; /** * The type attribute appender factory to apply to any type that is generated by this configuration. */ protected final TypeAttributeAppender typeAttributeAppender; /** * The default field attribute appender factory which is applied to any field that is defined * for instrumentations that are applied by this configuration. */ protected final FieldAttributeAppender.Factory defaultFieldAttributeAppenderFactory; /** * The default method attribute appender factory which is applied to any method that is defined * or intercepted for instrumentations that are applied by this configuration. */ protected final MethodAttributeAppender.Factory defaultMethodAttributeAppenderFactory; /** * Defines a new {@code ByteBuddy} default configuration for the current Java virtual machine's * class file version. */ public ByteBuddy() { this(ClassFileVersion.forCurrentJavaVersion()); } /** * Defines a new {@code ByteBuddy} default configuration for the given class file version. * * @param classFileVersion The class file version to apply. */ public ByteBuddy(ClassFileVersion classFileVersion) { this(classFileVersion, new NamingStrategy.SuffixingRandom(BYTE_BUDDY_DEFAULT_PREFIX), new TypeList.Empty(), isDefaultFinalizer().or(isSynthetic().and(not(isVisibilityBridge()))), BridgeMethodResolver.Simple.Factory.FAIL_ON_REQUEST, new ClassVisitorWrapper.Chain(), new MethodRegistry.Default(), new Definable.Undefined(), TypeAttributeAppender.NoOp.INSTANCE, MethodLookupEngine.Default.Factory.INSTANCE, FieldAttributeAppender.NoOp.INSTANCE, MethodAttributeAppender.NoOp.INSTANCE); } /** * Defines a new {@code ByteBuddy} configuration. * * @param classFileVersion The currently defined class file version. * @param namingStrategy The currently defined naming strategy. * @param interfaceTypes The currently defined collection of interfaces to be implemented * by any dynamically created type. * @param ignoredMethods The methods to always be ignored. * @param bridgeMethodResolverFactory The bridge method resolver factory to be applied to any instrumentation * process. * @param classVisitorWrapperChain The class visitor wrapper chain to be applied to any instrumentation * process. * @param methodRegistry The currently valid method registry. * @param modifiers The modifiers to define for any instrumentation process. * @param typeAttributeAppender The type attribute appender to apply to any instrumentation process. * @param methodLookupEngineFactory The method lookup engine factory to apply to this configuration. * @param defaultFieldAttributeAppenderFactory The field attribute appender to apply as a default for any field * definition. * @param defaultMethodAttributeAppenderFactory The method attribute appender to apply as a default for any * method definition or instrumentation. */ protected ByteBuddy(ClassFileVersion classFileVersion, NamingStrategy namingStrategy, List interfaceTypes, MethodMatcher ignoredMethods, BridgeMethodResolver.Factory bridgeMethodResolverFactory, ClassVisitorWrapper.Chain classVisitorWrapperChain, MethodRegistry methodRegistry, Definable modifiers, TypeAttributeAppender typeAttributeAppender, MethodLookupEngine.Factory methodLookupEngineFactory, FieldAttributeAppender.Factory defaultFieldAttributeAppenderFactory, MethodAttributeAppender.Factory defaultMethodAttributeAppenderFactory) { this.classFileVersion = classFileVersion; this.namingStrategy = namingStrategy; this.interfaceTypes = interfaceTypes; this.ignoredMethods = ignoredMethods; this.bridgeMethodResolverFactory = bridgeMethodResolverFactory; this.classVisitorWrapperChain = classVisitorWrapperChain; this.methodRegistry = methodRegistry; this.modifiers = modifiers; this.typeAttributeAppender = typeAttributeAppender; this.methodLookupEngineFactory = methodLookupEngineFactory; this.defaultFieldAttributeAppenderFactory = defaultFieldAttributeAppenderFactory; this.defaultMethodAttributeAppenderFactory = defaultMethodAttributeAppenderFactory; } /** * Returns the class file version that is defined for the current configuration. * * @return The class file version that is defined for this configuration. */ public ClassFileVersion getClassFileVersion() { return classFileVersion; } /** * Returns the naming strategy for the current configuration. * * @return The naming strategy for the current configuration. */ public NamingStrategy getNamingStrategy() { return namingStrategy; } /** * Returns the naming strategy for the current configuration. * * @return The naming strategy for the current configuration. */ public List getInterfaceTypes() { return Collections.unmodifiableList(interfaceTypes); } /** * Returns the matcher for the ignored methods for the current configuration. * * @return The matcher for the ignored methods for the current configuration. */ public MethodMatcher getIgnoredMethods() { return ignoredMethods; } /** * Returns the factory for the bridge method resolver for the current configuration. * * @return The factory for the bridge method resolver for the current configuration. */ public BridgeMethodResolver.Factory getBridgeMethodResolverFactory() { return bridgeMethodResolverFactory; } /** * Returns the class visitor wrapper chain for the current configuration. * * @return The class visitor wrapper chain for the current configuration. */ public ClassVisitorWrapper.Chain getClassVisitorWrapperChain() { return classVisitorWrapperChain; } /** * Returns the method registry for the current configuration. * * @return The method registry for the current configuration. */ public MethodRegistry getMethodRegistry() { return methodRegistry; } /** * Returns the modifiers to apply to any type that is generated by this configuration. * * @return The modifiers to apply to any type that is generated by this configuration. */ public Definable getModifiers() { return modifiers; } /** * Returns the method lookup engine factory to apply to any type that is generated by this configuration. * * @return The method lookup engine factory to apply to any type that is generated by this configuration. */ public MethodLookupEngine.Factory getMethodLookupEngineFactory() { return methodLookupEngineFactory; } /** * Returns the type attribute appender factory to apply to any type that is generated by this configuration. * * @return The type attribute appender factory to apply to any type that is generated by this configuration. */ public TypeAttributeAppender getTypeAttributeAppender() { return typeAttributeAppender; } /** * Returns the default field attribute appender factory which is applied to any field that is defined * for instrumentations that are applied by this configuration. * * @return The default field attribute appender factory which is applied to any field that is defined * for instrumentations that are applied by this configuration. */ public FieldAttributeAppender.Factory getDefaultFieldAttributeAppenderFactory() { return defaultFieldAttributeAppenderFactory; } /** * Returns the default method attribute appender factory which is applied to any method that is defined * or intercepted for instrumentations that are applied by this configuration. * * @return The default method attribute appender factory which is applied to any method that is defined * or intercepted for instrumentations that are applied by this configuration. */ public MethodAttributeAppender.Factory getDefaultMethodAttributeAppenderFactory() { return defaultMethodAttributeAppenderFactory; } /** * Creates a dynamic type builder that creates a subclass of a given loaded type where the subclass * is created by the {@link net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy.Default#IMITATE_SUPER_TYPE} * strategy. * * @param superType The type or interface to be extended or implemented by the dynamic type. * @param The most specific known type that the created dynamic type represents. * @return A dynamic type builder for this configuration that extends or implements the given loaded type. */ public DynamicType.Builder subclass(Class superType) { return subclass(superType, ConstructorStrategy.Default.IMITATE_SUPER_TYPE); } /** * Creates a dynamic type builder that creates a subclass of a given loaded type. * * @param superType The type or interface to be extended or implemented by the dynamic type. * @param constructorStrategy The constructor strategy to apply. * @param The most specific known type that the created dynamic type represents. * @return A dynamic type builder for this configuration that extends or implements the given loaded type. */ public DynamicType.Builder subclass(Class superType, ConstructorStrategy constructorStrategy) { return subclass(new TypeDescription.ForLoadedType(superType), constructorStrategy); } /** * Creates a dynamic type builder that creates a subclass of a given type description where the subclass * is created by the {@link net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy.Default#IMITATE_SUPER_TYPE} * strategy. * * @param superType The type or interface to be extended or implemented by the dynamic type. * @param The most specific known type that the created dynamic type represents. * @return A dynamic type builder for this configuration that extends or implements the given type description. */ public DynamicType.Builder subclass(TypeDescription superType) { return subclass(superType, ConstructorStrategy.Default.IMITATE_SUPER_TYPE); } /** * Creates a dynamic type builder that creates a subclass of a given type description. * * @param superType The type or interface to be extended or implemented by the dynamic type. * @param constructorStrategy The constructor strategy to apply. * @param The most specific known type that the created dynamic type represents. * @return A dynamic type builder for this configuration that extends or implements the given type description. */ public DynamicType.Builder subclass(TypeDescription superType, ConstructorStrategy constructorStrategy) { TypeDescription actualSuperType = isExtendable(superType); List interfaceTypes = this.interfaceTypes; if (nonNull(superType).isInterface()) { actualSuperType = new TypeDescription.ForLoadedType(Object.class); interfaceTypes = join(superType, interfaceTypes); } return new SubclassDynamicTypeBuilder(classFileVersion, namingStrategy, actualSuperType, interfaceTypes, modifiers.resolve(superType.getModifiers() & ~TypeManifestation.INTERFACE.getMask()), typeAttributeAppender, ignoredMethods, bridgeMethodResolverFactory, classVisitorWrapperChain, new FieldRegistry.Default(), methodRegistry, methodLookupEngineFactory, defaultFieldAttributeAppenderFactory, defaultMethodAttributeAppenderFactory, nonNull(constructorStrategy)); } /** *

* Creates a dynamic type builder for redefining of the given type. The given class must be found on the * class path or by the class's {@link java.lang.ClassLoader}. Otherwise, the class file to the redefined class * must be located explicitly by providing a locator by * {@link net.bytebuddy.ByteBuddy#redefine(Class, net.bytebuddy.dynamic.scaffold.inline.ClassFileLocator)}. *

*

* Note: It is possible to experience unexpected errors in case that the provided {@code levelType} and the * corresponding class file get out of sync, i.e. a type is redefined several times without providing an updated * version of the class file. *

* * @param levelType The type to redefine. * @param The most specific known type that the created dynamic type represents. * @return A dynamic type builder for this configuration that redefines the given type description. */ public DynamicType.Builder redefine(Class levelType) { return redefine(new TypeDescription.ForLoadedType(levelType), ClassFileLocator.Compound.makeDefault()); } /** *

* Creates a dynamic type builder for redefining of the given type. *

*

* Note: It is possible to experience unexpected errors in case that the provided {@code levelType} and the * corresponding class file get out of sync, i.e. a type is redefined several times without providing an updated * version of the class file. *

* * @param levelType The type to redefine. * @param classFileLocator A locator for finding a class file that represents a type. * @param The most specific known type that the created dynamic type represents. * @return A dynamic type builder for this configuration that redefines the given type description. */ public DynamicType.Builder redefine(Class levelType, ClassFileLocator classFileLocator) { return redefine(new TypeDescription.ForLoadedType(levelType), classFileLocator); } /** *

* Creates a dynamic type builder for redefining of the given type. The given class must be found on the * class path. Otherwise, the class file to the redefined class must be located explicitly by providing a locator * by {@link net.bytebuddy.ByteBuddy#redefine(Class, net.bytebuddy.dynamic.scaffold.inline.ClassFileLocator)}. *

*

* Note: It is possible to experience unexpected errors in case that the provided {@code levelType} and the * corresponding class file get out of sync, i.e. a type is redefined several times without providing an updated * version of the class file. *

* * @param levelType The type to redefine. * @param The most specific known type that the created dynamic type represents. * @return A dynamic type builder for this configuration that redefines the given type description. */ public DynamicType.Builder redefine(TypeDescription levelType) { return redefine(levelType, ClassFileLocator.Compound.makeDefault()); } /** *

* Creates a dynamic type builder for redefining of the given type. *

*

* Note: It is possible to experience unexpected errors in case that the provided {@code levelType} and the * corresponding class file get out of sync, i.e. a type is redefined several times without providing an updated * version of the class file. *

* * @param levelType The type to redefine. * @param classFileLocator A locator for finding a class file that represents a type. * @param The most specific known type that the created dynamic type represents. * @return A dynamic type builder for this configuration that redefines the given type description. */ public DynamicType.Builder redefine(TypeDescription levelType, ClassFileLocator classFileLocator) { return new InlineDynamicTypeBuilder(classFileVersion, new NamingStrategy.Fixed(levelType.getName()), nonNull(levelType), interfaceTypes, modifiers.resolve(levelType.getModifiers()), typeAttributeAppender, ignoredMethods, bridgeMethodResolverFactory, classVisitorWrapperChain, new FieldRegistry.Default(), methodRegistry, methodLookupEngineFactory, defaultFieldAttributeAppenderFactory, defaultMethodAttributeAppenderFactory, nonNull(classFileLocator), InlineDynamicTypeBuilder.TargetHandler.ForRedefinitionInstrumentation.INSTANCE); } /** *

* Creates a dynamic type by weaving any changes into an already defined level type. The rebased type is * created by adding methods to the level type where the original method implementations are copied to * renamed, private methods within the created dynamic type and therefore remain invokable as super method calls. * The result is a rebased type with subclass semantics. The given class must be found on the class path or * by the provided class's {@link java.lang.ClassLoader}. Otherwise, the class file to the redefined class * must be located explicitly by providing a locator by * {@link net.bytebuddy.ByteBuddy#rebase(Class, net.bytebuddy.dynamic.scaffold.inline.ClassFileLocator)}. *

*

* Note: It is possible to experience unexpected errors in case that the provided {@code levelType} and the * corresponding class file get out of sync, i.e. a type is rebased several times without updating the class file. *

* * @param levelType The type which is to be rebased. * @param The most specific known type that the created dynamic type represents. * @return A dynamic type builder for this configuration that creates a rebased version of the given type. */ public DynamicType.Builder rebase(Class levelType) { return rebase(new TypeDescription.ForLoadedType(levelType), ClassFileLocator.Compound.makeDefault()); } /** *

* Creates a dynamic type by weaving any changes into an already defined level type. The rebased type is * created by adding methods to the level type where the original method implementations are copied to * renamed, private methods within the created dynamic type and therefore remain invokable as super method calls. * The result is a rebased type with subclass semantics. *

*

* Note: It is possible to experience unexpected errors in case that the provided {@code levelType} and the * corresponding class file get out of sync, i.e. a type is rebased several times without updating the class file. *

* * @param levelType The type which is to be rebased. * @param classFileLocator A locator for finding a class file that represents a type. * @param The most specific known type that the created dynamic type represents. * @return A dynamic type builder for this configuration that creates a rebased version of the given type. */ public DynamicType.Builder rebase(Class levelType, ClassFileLocator classFileLocator) { return rebase(new TypeDescription.ForLoadedType(levelType), classFileLocator); } /** *

* Creates a dynamic type by weaving any changes into an already defined level type. The rebased type is * created by adding methods to the level type where the original method implementations are copied to * renamed, private methods within the created dynamic type and therefore remain invokable as super method calls. * The result is a rebased type with subclass semantics. The given class must be found on the class path. * Otherwise, the class file to the redefined class must be located explicitly by providing a locator by * {@link net.bytebuddy.ByteBuddy#rebase(Class, net.bytebuddy.dynamic.scaffold.inline.ClassFileLocator)}. *

*

* Note: It is possible to experience unexpected errors in case that the provided {@code levelType} and the * corresponding class file get out of sync, i.e. a type is rebased several times without updating the class file. *

* * @param levelType The type which is to be rebased. * @param The most specific known type that the created dynamic type represents. * @return A dynamic type builder for this configuration that creates a rebased version of the given type. */ public DynamicType.Builder rebase(TypeDescription levelType) { return rebase(levelType, ClassFileLocator.Compound.makeDefault()); } /** *

* Creates a dynamic type by weaving any changes into an already defined level type. The rebased type is * created by adding methods to the level type where the original method implementations are copied to * renamed, private methods within the created dynamic type and therefore remain invokable as super method calls. * The result is a rebased type with subclass semantics. *

*

* Note: It is possible to experience unexpected errors in case that the provided {@code levelType} and the * corresponding class file get out of sync, i.e. a type is rebased several times without updating the class file. *

* * @param levelType The type which is to be rebased. * @param classFileLocator A locator for finding a class file that represents a type. * @param The most specific known type that the created dynamic type represents. * @return A dynamic type builder for this configuration that creates a rebased version of the given type. */ public DynamicType.Builder rebase(TypeDescription levelType, ClassFileLocator classFileLocator) { return new InlineDynamicTypeBuilder(classFileVersion, new NamingStrategy.Fixed(levelType.getName()), nonNull(levelType), interfaceTypes, modifiers.resolve(levelType.getModifiers()), TypeAttributeAppender.NoOp.INSTANCE, ignoredMethods, bridgeMethodResolverFactory, classVisitorWrapperChain, new FieldRegistry.Default(), methodRegistry, methodLookupEngineFactory, defaultFieldAttributeAppenderFactory, defaultMethodAttributeAppenderFactory, nonNull(classFileLocator), InlineDynamicTypeBuilder.TargetHandler.ForRebaseInstrumentation.INSTANCE); } /** * Defines a new class file version for this configuration. * * @param classFileVersion The class file version to define for this configuration. * @return A new configuration that represents this configuration with the given class file version. */ public ByteBuddy withClassFileVersion(ClassFileVersion classFileVersion) { return new ByteBuddy(nonNull(classFileVersion), namingStrategy, interfaceTypes, ignoredMethods, bridgeMethodResolverFactory, classVisitorWrapperChain, methodRegistry, modifiers, typeAttributeAppender, methodLookupEngineFactory, defaultFieldAttributeAppenderFactory, defaultMethodAttributeAppenderFactory); } /** * Defines a new naming strategy for this configuration. * * @param namingStrategy The class format version to define for this configuration. * @return A new configuration that represents this configuration with the given class format version. */ public ByteBuddy withNamingStrategy(NamingStrategy namingStrategy) { return new ByteBuddy(classFileVersion, nonNull(namingStrategy), interfaceTypes, ignoredMethods, bridgeMethodResolverFactory, classVisitorWrapperChain, methodRegistry, modifiers, typeAttributeAppender, methodLookupEngineFactory, defaultFieldAttributeAppenderFactory, defaultMethodAttributeAppenderFactory); } /** * Defines a new modifier contributors for this configuration that replaces the currently defined modifier * contributes which might currently be implicit. * * @param modifierContributor The modifier contributors to define explicitly for this configuration. * @return A new configuration that represents this configuration with the given modifier contributors. */ public ByteBuddy withModifiers(ModifierContributor.ForType... modifierContributor) { return new ByteBuddy(classFileVersion, namingStrategy, interfaceTypes, ignoredMethods, bridgeMethodResolverFactory, classVisitorWrapperChain, methodRegistry, new Definable.Defined(resolveModifierContributors(TYPE_MODIFIER_MASK, nonNull(modifierContributor))), typeAttributeAppender, methodLookupEngineFactory, defaultFieldAttributeAppenderFactory, defaultMethodAttributeAppenderFactory); } /** * Defines a new type attribute appender for this configuration that replaces the currently defined type * attribute appender. * * @param typeAttributeAppender The type attribute appender to define for this configuration. * @return A new configuration that represents this configuration with the given type attribute appender. */ public ByteBuddy withAttribute(TypeAttributeAppender typeAttributeAppender) { return new ByteBuddy(classFileVersion, namingStrategy, interfaceTypes, ignoredMethods, bridgeMethodResolverFactory, classVisitorWrapperChain, methodRegistry, modifiers, nonNull(typeAttributeAppender), methodLookupEngineFactory, defaultFieldAttributeAppenderFactory, defaultMethodAttributeAppenderFactory); } /** * Defines a new type annotation for this configuration that replaces the currently defined type * attribute appender. * * @param annotation The type annotations to define for this configuration. * @return A new configuration that represents this configuration with the given annotations as its new * type attribute appender. */ public ByteBuddy withTypeAnnotation(Annotation... annotation) { return new ByteBuddy(classFileVersion, namingStrategy, interfaceTypes, ignoredMethods, bridgeMethodResolverFactory, classVisitorWrapperChain, methodRegistry, modifiers, new TypeAttributeAppender.ForAnnotation(nonNull(annotation)), methodLookupEngineFactory, defaultFieldAttributeAppenderFactory, defaultMethodAttributeAppenderFactory); } /** * Defines all dynamic types that are created by this configuration to implement the given interface. * * @param type The interface type to implement. * @return This configuration where any dynamic type that is created by the resulting configuration will * implement the given interface. */ public OptionalMethodInterception withImplementing(Class... type) { TypeDescription[] typeDescription = new TypeDescription[type.length]; int index = 0; for (Class aType : type) { typeDescription[index++] = new TypeDescription.ForLoadedType(aType); } return withImplementing(typeDescription); } /** * Defines all dynamic types that are created by this configuration to implement the given interface. * * @param type The interface type to implement. * @return The same configuration where any dynamic type that is created by the resulting configuration will * implement the given interface. */ public OptionalMethodInterception withImplementing(TypeDescription... type) { return new OptionalMethodInterception(classFileVersion, namingStrategy, join(interfaceTypes, isInterface(Arrays.asList(type))), ignoredMethods, bridgeMethodResolverFactory, classVisitorWrapperChain, methodRegistry, modifiers, typeAttributeAppender, methodLookupEngineFactory, defaultFieldAttributeAppenderFactory, defaultMethodAttributeAppenderFactory, isDeclaredByAny(type)); } /** * Defines a new method matcher for methods that are ignored by any dynamic type that is created by this * configuration which will replace the current configuration. By default, this method matcher is defined * to ignore instrumenting synthetic methods and the default finalizer method. The only exception from per-default * overridable synthetic methods are bridge methods which is only implemented by the Java compiler to increase a * method's visibility. * * @param ignoredMethods The methods to always be ignored for any instrumentation. * @return A new configuration that represents this configuration with the given method matcher defining methods * that are to be ignored for any instrumentation. */ public ByteBuddy withIgnoredMethods(MethodMatcher ignoredMethods) { return new ByteBuddy(classFileVersion, namingStrategy, interfaceTypes, nonNull(ignoredMethods), bridgeMethodResolverFactory, classVisitorWrapperChain, methodRegistry, modifiers, typeAttributeAppender, methodLookupEngineFactory, defaultFieldAttributeAppenderFactory, defaultMethodAttributeAppenderFactory); } /** * Defines a bridge method resolver factory to be applied to this configuration. A bridge method resolver is * responsible for determining the target method that is invoked by a bridge method. This way, a super method * invocation is resolved by invoking the actual super method instead of the bridge method which would in turn * resolve the actual method virtually. * * @param bridgeMethodResolverFactory The bridge method resolver factory to be applied to any instrumentation * process. * @return A new configuration that represents this configuration with the given bridge method resolver factory * to be applied on any configuration. */ public ByteBuddy withBridgeMethodResolver(BridgeMethodResolver.Factory bridgeMethodResolverFactory) { return new ByteBuddy(classFileVersion, namingStrategy, interfaceTypes, ignoredMethods, nonNull(bridgeMethodResolverFactory), classVisitorWrapperChain, methodRegistry, modifiers, typeAttributeAppender, methodLookupEngineFactory, defaultFieldAttributeAppenderFactory, defaultMethodAttributeAppenderFactory); } /** * Defines a new class visitor to be appended to the current collection of {@link net.bytebuddy.jar.asm.ClassVisitor}s * that are to be applied onto any creation process of a dynamic type. * * @param classVisitorWrapper The class visitor wrapper to ba appended to the current chain of class visitor wrappers. * @return The same configuration with the given class visitor wrapper to be applied onto any creation process of a dynamic * type. */ public ByteBuddy withClassVisitor(ClassVisitorWrapper classVisitorWrapper) { return new ByteBuddy(classFileVersion, namingStrategy, interfaceTypes, ignoredMethods, bridgeMethodResolverFactory, classVisitorWrapperChain.append(nonNull(classVisitorWrapper)), methodRegistry, modifiers, typeAttributeAppender, methodLookupEngineFactory, defaultFieldAttributeAppenderFactory, defaultMethodAttributeAppenderFactory); } /** * Defines a new {@link net.bytebuddy.instrumentation.method.MethodLookupEngine.Factory} to be used for creating * {@link net.bytebuddy.instrumentation.method.MethodLookupEngine}s for type creations based on this configuration. * The default lookup engine queries any class or interface type that is represented by the created type. These * queries might however be costly such that this factory can be configured to save lookup time, for example * by providing additional caching or by providing precomputed results. * * @param methodLookupEngineFactory The method lookup engine factory to apply to this configuration. * @return The same configuration with the method lookup engine factory. */ public ByteBuddy withMethodLookupEngine(MethodLookupEngine.Factory methodLookupEngineFactory) { return new ByteBuddy(classFileVersion, namingStrategy, interfaceTypes, ignoredMethods, bridgeMethodResolverFactory, classVisitorWrapperChain, methodRegistry, modifiers, typeAttributeAppender, nonNull(methodLookupEngineFactory), defaultFieldAttributeAppenderFactory, defaultMethodAttributeAppenderFactory); } /** * Defines a new default field attribute appender factory that is applied onto any field. * * @param attributeAppenderFactory The attribute appender factory that is applied as a default on any * field that is created by a dynamic type that is created with this * configuration. * @return The same configuration with the given field attribute appender factory to be applied as a default to * the creation process of any field of a dynamic type. */ public ByteBuddy withDefaultFieldAttributeAppender(FieldAttributeAppender.Factory attributeAppenderFactory) { return new ByteBuddy(classFileVersion, namingStrategy, interfaceTypes, ignoredMethods, bridgeMethodResolverFactory, classVisitorWrapperChain, methodRegistry, modifiers, typeAttributeAppender, methodLookupEngineFactory, nonNull(attributeAppenderFactory), defaultMethodAttributeAppenderFactory); } /** * Defines a new default method attribute appender factory that is applied onto any method. * * @param attributeAppenderFactory The attribute appender factory that is applied as a default on any * method that is created or intercepted by a dynamic type that is created * with this configuration. * @return The same configuration with the given method attribute appender factory to be applied as a default to * the creation or interception process of any method of a dynamic type. */ public ByteBuddy withDefaultMethodAttributeAppender(MethodAttributeAppender.Factory attributeAppenderFactory) { return new ByteBuddy(classFileVersion, namingStrategy, interfaceTypes, ignoredMethods, bridgeMethodResolverFactory, classVisitorWrapperChain, methodRegistry, modifiers, typeAttributeAppender, methodLookupEngineFactory, defaultFieldAttributeAppenderFactory, nonNull(attributeAppenderFactory)); } /** * Intercepts a given selection of byte code methods that can be a method or a constructor. * * @param methodMatcher The method matcher representing all byte code methods to intercept. * @return A matched method interception for the given selection. */ public MatchedMethodInterception invokable(MethodMatcher methodMatcher) { return new MatchedMethodInterception(nonNull(methodMatcher)); } /** * Intercepts a given method selection. * * @param methodMatcher The method matcher representing all methods to intercept. * @return A matched method interception for the given selection. */ public MatchedMethodInterception method(MethodMatcher methodMatcher) { return invokable(isMethod().and(nonNull(methodMatcher))); } /** * Intercepts a given constructor selection. * * @param methodMatcher The method matcher representing all constructors to intercept. * @return A matched method interception for the given selection. */ public MatchedMethodInterception constructor(MethodMatcher methodMatcher) { return invokable(isConstructor().and(nonNull(methodMatcher))); } @Override public boolean equals(Object other) { if (this == other) return true; if (other == null || getClass() != other.getClass()) return false; ByteBuddy byteBuddy = (ByteBuddy) other; return bridgeMethodResolverFactory.equals(byteBuddy.bridgeMethodResolverFactory) && classFileVersion.equals(byteBuddy.classFileVersion) && classVisitorWrapperChain.equals(byteBuddy.classVisitorWrapperChain) && defaultFieldAttributeAppenderFactory.equals(byteBuddy.defaultFieldAttributeAppenderFactory) && defaultMethodAttributeAppenderFactory.equals(byteBuddy.defaultMethodAttributeAppenderFactory) && ignoredMethods.equals(byteBuddy.ignoredMethods) && interfaceTypes.equals(byteBuddy.interfaceTypes) && methodLookupEngineFactory.equals(byteBuddy.methodLookupEngineFactory) && methodRegistry.equals(byteBuddy.methodRegistry) && modifiers.equals(byteBuddy.modifiers) && namingStrategy.equals(byteBuddy.namingStrategy) && typeAttributeAppender.equals(byteBuddy.typeAttributeAppender); } @Override public int hashCode() { int result = classFileVersion.hashCode(); result = 31 * result + namingStrategy.hashCode(); result = 31 * result + interfaceTypes.hashCode(); result = 31 * result + ignoredMethods.hashCode(); result = 31 * result + bridgeMethodResolverFactory.hashCode(); result = 31 * result + classVisitorWrapperChain.hashCode(); result = 31 * result + methodRegistry.hashCode(); result = 31 * result + modifiers.hashCode(); result = 31 * result + methodLookupEngineFactory.hashCode(); result = 31 * result + typeAttributeAppender.hashCode(); result = 31 * result + defaultFieldAttributeAppenderFactory.hashCode(); result = 31 * result + defaultMethodAttributeAppenderFactory.hashCode(); return result; } @Override public String toString() { return "ByteBuddy{" + "classFileVersion=" + classFileVersion + ", namingStrategy=" + namingStrategy + ", interfaceTypes=" + interfaceTypes + ", ignoredMethods=" + ignoredMethods + ", bridgeMethodResolverFactory=" + bridgeMethodResolverFactory + ", classVisitorWrapperChain=" + classVisitorWrapperChain + ", methodRegistry=" + methodRegistry + ", modifiers=" + modifiers + ", methodLookupEngineFactory=" + methodLookupEngineFactory + ", typeAttributeAppender=" + typeAttributeAppender + ", defaultFieldAttributeAppenderFactory=" + defaultFieldAttributeAppenderFactory + ", defaultMethodAttributeAppenderFactory=" + defaultMethodAttributeAppenderFactory + '}'; } /** * Any definable instance is either {@link net.bytebuddy.ByteBuddy.Definable.Defined} when a value is provided * or {@link net.bytebuddy.ByteBuddy.Definable.Undefined} if a value is not provided. A defined definable will * return its defined value on request while an undefined definable will return the provided default. * * @param The type of the definable object. */ protected static interface Definable { /** * Returns the value of this instance or the provided default value for an undefined definable. * * @param defaultValue The default value that is returned for an {@link net.bytebuddy.ByteBuddy.Definable.Undefined} * definable. * @return The value that is represented by this instance. */ T resolve(T defaultValue); /** * Checks if this value is explicitly defined. * * @return {@code true} if this value is defined. */ boolean isDefined(); /** * A representation of an undefined {@link net.bytebuddy.ByteBuddy.Definable}. * * @param The type of the definable object. */ static class Undefined implements Definable { @Override public T resolve(T defaultValue) { return defaultValue; } @Override public boolean isDefined() { return false; } @Override public boolean equals(Object other) { return other != null && other.getClass() == Undefined.class; } @Override public int hashCode() { return 31; } @Override public String toString() { return "ByteBuddy.Definable.Undefined{}"; } } /** * A representation of a defined {@link net.bytebuddy.ByteBuddy.Definable} for a given value. * * @param The type of the definable object. */ static class Defined implements Definable { /** * The value that is represented by this defined definable. */ private final T value; /** * Creates a new defined instance for the given value. * * @param value The defined value. */ public Defined(T value) { this.value = value; } @Override public T resolve(T defaultValue) { return value; } @Override public boolean isDefined() { return true; } @Override public boolean equals(Object o) { return this == o || !(o == null || getClass() != o.getClass()) && value.equals(((Defined) o).value); } @Override public int hashCode() { return value.hashCode(); } @Override public String toString() { return "ByteBuddy.Definable.Defined{value=" + value + '}'; } } } /** * Implementations of this interface are capable of defining a method interception for a given set of methods. */ public static interface MethodInterceptable { /** * Intercepts the given method with the given instrumentation. * * @param instrumentation The instrumentation to apply to the selected methods. * @return A method annotation target for this instance with the given instrumentation applied to the * current selection. */ MethodAnnotationTarget intercept(Instrumentation instrumentation); /** * Defines the currently selected methods as {@code abstract}. * * @return A method annotation target for this instance with implementing the currently selected methods * as {@code abstract}. */ MethodAnnotationTarget withoutCode(); } /** * A {@link net.bytebuddy.ByteBuddy} configuration with a selected set of methods for which annotations can * be defined. */ public static class MethodAnnotationTarget extends ByteBuddy { /** * The method matcher representing the current method selection. */ protected final MethodMatcher methodMatcher; /** * The instrumentation that was defined for the current method selection. */ protected final Instrumentation instrumentation; /** * The method attribute appender factory that was defined for the current method selection. */ protected final MethodAttributeAppender.Factory attributeAppenderFactory; /** * Creates a new method annotation target. * * @param classFileVersion The currently defined class file version. * @param namingStrategy The currently defined naming strategy. * @param interfaceTypes The currently defined collection of interfaces to be implemented * by any dynamically created type. * @param ignoredMethods The methods to always be ignored. * @param bridgeMethodResolverFactory The bridge method resolver factory to be applied to any instrumentation * process. * @param classVisitorWrapperChain The class visitor wrapper chain to be applied to any instrumentation * process. * @param methodRegistry The currently valid method registry. * @param modifiers The modifiers to define for any instrumentation process. * @param typeAttributeAppender The type attribute appender to apply to any instrumentation process. * @param methodLookupEngineFactory The method lookup engine factory to apply to this configuration. * @param defaultFieldAttributeAppenderFactory The field attribute appender to apply as a default for any field * definition. * @param defaultMethodAttributeAppenderFactory The method attribute appender to apply as a default for any * method definition or instrumentation. * @param methodMatcher The method matcher representing the current method selection. * @param instrumentation The instrumentation that was defined for the current method * selection. * @param attributeAppenderFactory The method attribute appender factory that was defined for the * current method selection. */ protected MethodAnnotationTarget(ClassFileVersion classFileVersion, NamingStrategy namingStrategy, List interfaceTypes, MethodMatcher ignoredMethods, BridgeMethodResolver.Factory bridgeMethodResolverFactory, ClassVisitorWrapper.Chain classVisitorWrapperChain, MethodRegistry methodRegistry, Definable modifiers, TypeAttributeAppender typeAttributeAppender, MethodLookupEngine.Factory methodLookupEngineFactory, FieldAttributeAppender.Factory defaultFieldAttributeAppenderFactory, MethodAttributeAppender.Factory defaultMethodAttributeAppenderFactory, MethodMatcher methodMatcher, Instrumentation instrumentation, MethodAttributeAppender.Factory attributeAppenderFactory) { super(classFileVersion, namingStrategy, interfaceTypes, ignoredMethods, bridgeMethodResolverFactory, classVisitorWrapperChain, methodRegistry, modifiers, typeAttributeAppender, methodLookupEngineFactory, defaultFieldAttributeAppenderFactory, defaultMethodAttributeAppenderFactory); this.methodMatcher = methodMatcher; this.instrumentation = instrumentation; this.attributeAppenderFactory = attributeAppenderFactory; } /** * Defines a given attribute appender factory to be applied for the currently selected methods. * * @param attributeAppenderFactory The method attribute appender factory to apply to the currently * selected methods. * @return A method annotation target that represents the current configuration with the additional * attribute appender factory applied to the current method selection. */ public MethodAnnotationTarget attribute(MethodAttributeAppender.Factory attributeAppenderFactory) { return new MethodAnnotationTarget(classFileVersion, namingStrategy, interfaceTypes, ignoredMethods, bridgeMethodResolverFactory, classVisitorWrapperChain, methodRegistry, modifiers, typeAttributeAppender, methodLookupEngineFactory, defaultFieldAttributeAppenderFactory, defaultMethodAttributeAppenderFactory, methodMatcher, instrumentation, new MethodAttributeAppender.Factory.Compound(this.attributeAppenderFactory, nonNull(attributeAppenderFactory))); } /** * Defines an method annotation for the currently selected methods. * * @param annotation The annotations to defined for the currently selected methods. * @return A method annotation target that represents the current configuration with the additional * annotations added to the currently selected methods. */ public MethodAnnotationTarget annotateMethod(Annotation... annotation) { return attribute(new MethodAttributeAppender.ForAnnotation(nonNull(annotation))); } /** * Defines an method annotation for a parameter of the currently selected methods. * * @param parameterIndex The index of the parameter for which the annotations should be applied * with the first parameter index by {@code 0}. * @param annotation The annotations to defined for the currently selected methods' parameters * ath the given index. * @return A method annotation target that represents the current configuration with the additional * annotations added to the currently selected methods' parameters at the given index. */ public MethodAnnotationTarget annotateParameter(int parameterIndex, Annotation... annotation) { return attribute(new MethodAttributeAppender.ForAnnotation(parameterIndex, nonNull(annotation))); } @Override public ClassFileVersion getClassFileVersion() { return materialize().getClassFileVersion(); } @Override public NamingStrategy getNamingStrategy() { return materialize().getNamingStrategy(); } @Override public List getInterfaceTypes() { return materialize().getInterfaceTypes(); } @Override public MethodMatcher getIgnoredMethods() { return materialize().getIgnoredMethods(); } @Override public ClassVisitorWrapper.Chain getClassVisitorWrapperChain() { return materialize().getClassVisitorWrapperChain(); } @Override public BridgeMethodResolver.Factory getBridgeMethodResolverFactory() { return materialize().getBridgeMethodResolverFactory(); } @Override public MethodRegistry getMethodRegistry() { return materialize().getMethodRegistry(); } @Override public Definable getModifiers() { return materialize().getModifiers(); } @Override public MethodLookupEngine.Factory getMethodLookupEngineFactory() { return materialize().getMethodLookupEngineFactory(); } @Override public TypeAttributeAppender getTypeAttributeAppender() { return materialize().getTypeAttributeAppender(); } @Override public ByteBuddy withMethodLookupEngine(MethodLookupEngine.Factory methodLookupEngineFactory) { return materialize().withMethodLookupEngine(methodLookupEngineFactory); } @Override public FieldAttributeAppender.Factory getDefaultFieldAttributeAppenderFactory() { return materialize().getDefaultFieldAttributeAppenderFactory(); } @Override public MethodAttributeAppender.Factory getDefaultMethodAttributeAppenderFactory() { return materialize().getDefaultMethodAttributeAppenderFactory(); } @Override public DynamicType.Builder subclass(Class superType) { return materialize().subclass(superType); } @Override public DynamicType.Builder subclass(Class superType, ConstructorStrategy constructorStrategy) { return materialize().subclass(superType, constructorStrategy); } @Override public DynamicType.Builder subclass(TypeDescription superType) { return materialize().subclass(superType); } @Override public DynamicType.Builder subclass(TypeDescription superType, ConstructorStrategy constructorStrategy) { return materialize().subclass(superType, constructorStrategy); } @Override public ByteBuddy withModifiers(ModifierContributor.ForType... modifierContributor) { return materialize().withModifiers(modifierContributor); } @Override public ByteBuddy withAttribute(TypeAttributeAppender typeAttributeAppender) { return materialize().withAttribute(typeAttributeAppender); } @Override public ByteBuddy withBridgeMethodResolver(BridgeMethodResolver.Factory bridgeMethodResolverFactory) { return materialize().withBridgeMethodResolver(bridgeMethodResolverFactory); } @Override public ByteBuddy withTypeAnnotation(Annotation... annotation) { return materialize().withTypeAnnotation(annotation); } @Override public ByteBuddy withClassFileVersion(ClassFileVersion classFileVersion) { return materialize().withClassFileVersion(classFileVersion); } @Override public ByteBuddy withNamingStrategy(NamingStrategy namingStrategy) { return materialize().withNamingStrategy(namingStrategy); } @Override public OptionalMethodInterception withImplementing(Class... type) { return materialize().withImplementing(type); } @Override public OptionalMethodInterception withImplementing(TypeDescription... type) { return materialize().withImplementing(type); } @Override public ByteBuddy withIgnoredMethods(MethodMatcher ignoredMethods) { return materialize().withIgnoredMethods(ignoredMethods); } @Override public ByteBuddy withClassVisitor(ClassVisitorWrapper classVisitorWrapper) { return materialize().withClassVisitor(classVisitorWrapper); } @Override public ByteBuddy withDefaultFieldAttributeAppender(FieldAttributeAppender.Factory attributeAppenderFactory) { return materialize().withDefaultFieldAttributeAppender(attributeAppenderFactory); } @Override public ByteBuddy withDefaultMethodAttributeAppender(MethodAttributeAppender.Factory attributeAppenderFactory) { return materialize().withDefaultMethodAttributeAppender(attributeAppenderFactory); } @Override public MatchedMethodInterception invokable(MethodMatcher methodMatcher) { return materialize().invokable(methodMatcher); } /** * Materializes this configuration as new {@code ByteBuddy} instance. * * @return A {@code ByteBuddy} instance representing the current configuration. */ protected ByteBuddy materialize() { return new ByteBuddy(classFileVersion, namingStrategy, interfaceTypes, ignoredMethods, bridgeMethodResolverFactory, classVisitorWrapperChain, methodRegistry.prepend(new MethodRegistry.LatentMethodMatcher.Simple(methodMatcher), instrumentation, attributeAppenderFactory), modifiers, typeAttributeAppender, methodLookupEngineFactory, defaultFieldAttributeAppenderFactory, defaultMethodAttributeAppenderFactory ); } @Override public boolean equals(Object other) { if (this == other) return true; if (other == null || getClass() != other.getClass()) return false; if (!super.equals(other)) return false; MethodAnnotationTarget that = (MethodAnnotationTarget) other; return attributeAppenderFactory.equals(that.attributeAppenderFactory) && instrumentation.equals(that.instrumentation) && methodMatcher.equals(that.methodMatcher); } @Override public int hashCode() { int result = super.hashCode(); result = 31 * result + methodMatcher.hashCode(); result = 31 * result + instrumentation.hashCode(); result = 31 * result + attributeAppenderFactory.hashCode(); return result; } @Override public String toString() { return "ByteBuddy.MethodAnnotationTarget{" + "base=" + super.toString() + ", methodMatcher=" + methodMatcher + ", instrumentation=" + instrumentation + ", attributeAppenderFactory=" + attributeAppenderFactory + '}'; } } /** * An optional method interception that allows to intercept a method selection only if this is needed. */ public static class OptionalMethodInterception extends ByteBuddy implements MethodInterceptable { /** * The method matcher that defines the selected that is represented by this instance. */ protected final MethodMatcher methodMatcher; /** * Creates a new optional method interception. * * @param classFileVersion The currently defined class file version. * @param namingStrategy The currently defined naming strategy. * @param interfaceTypes The currently defined collection of interfaces to be implemented * by any dynamically created type. * @param ignoredMethods The methods to always be ignored. * @param bridgeMethodResolverFactory The bridge method resolver factory to be applied to any instrumentation * process. * @param classVisitorWrapperChain The class visitor wrapper chain to be applied to any instrumentation * process. * @param methodRegistry The currently valid method registry. * @param modifiers The modifiers to define for any instrumentation process. * @param typeAttributeAppender The type attribute appender to apply to any instrumentation process. * @param methodLookupEngineFactory The method lookup engine factory to apply to this configuration. * @param defaultFieldAttributeAppenderFactory The field attribute appender to apply as a default for any field * definition. * @param defaultMethodAttributeAppenderFactory The method attribute appender to apply as a default for any * method definition or instrumentation. * @param methodMatcher The method matcher representing the current method selection. */ protected OptionalMethodInterception(ClassFileVersion classFileVersion, NamingStrategy namingStrategy, List interfaceTypes, MethodMatcher ignoredMethods, BridgeMethodResolver.Factory bridgeMethodResolverFactory, ClassVisitorWrapper.Chain classVisitorWrapperChain, MethodRegistry methodRegistry, Definable modifiers, TypeAttributeAppender typeAttributeAppender, MethodLookupEngine.Factory methodLookupEngineFactory, FieldAttributeAppender.Factory defaultFieldAttributeAppenderFactory, MethodAttributeAppender.Factory defaultMethodAttributeAppenderFactory, MethodMatcher methodMatcher) { super(classFileVersion, namingStrategy, interfaceTypes, ignoredMethods, bridgeMethodResolverFactory, classVisitorWrapperChain, methodRegistry, modifiers, typeAttributeAppender, methodLookupEngineFactory, defaultFieldAttributeAppenderFactory, defaultMethodAttributeAppenderFactory); this.methodMatcher = methodMatcher; } @Override public MethodAnnotationTarget intercept(Instrumentation instrumentation) { return new MatchedMethodInterception(methodMatcher).intercept(instrumentation); } @Override public MethodAnnotationTarget withoutCode() { return new MatchedMethodInterception(methodMatcher).withoutCode(); } @Override public boolean equals(Object other) { return this == other || !(other == null || getClass() != other.getClass()) && super.equals(other) && methodMatcher.equals(((OptionalMethodInterception) other).methodMatcher); } @Override public int hashCode() { return 31 * methodMatcher.hashCode() + super.hashCode(); } @Override public String toString() { return "ByteBuddy.OptionalMethodInterception{" + "classFileVersion=" + classFileVersion + ", namingStrategy=" + namingStrategy + ", interfaceTypes=" + interfaceTypes + ", ignoredMethods=" + ignoredMethods + ", bridgeMethodResolverFactory=" + bridgeMethodResolverFactory + ", classVisitorWrapperChain=" + classVisitorWrapperChain + ", methodRegistry=" + methodRegistry + ", modifiers=" + modifiers + ", methodLookupEngineFactory=" + methodLookupEngineFactory + ", typeAttributeAppender=" + typeAttributeAppender + ", defaultFieldAttributeAppenderFactory=" + defaultFieldAttributeAppenderFactory + ", defaultMethodAttributeAppenderFactory=" + defaultMethodAttributeAppenderFactory + ", methodMatcher=" + methodMatcher + '}'; } } /** * A matched method interception for a non-optional method definition. */ public class MatchedMethodInterception implements MethodInterceptable { /** * A method matcher that represents the current method selection. */ protected final MethodMatcher methodMatcher; /** * Creates a new matched method interception. * * @param methodMatcher The method matcher representing the current method selection. */ protected MatchedMethodInterception(MethodMatcher methodMatcher) { this.methodMatcher = methodMatcher; } @Override public MethodAnnotationTarget intercept(Instrumentation instrumentation) { return new MethodAnnotationTarget(classFileVersion, namingStrategy, interfaceTypes, ignoredMethods, bridgeMethodResolverFactory, classVisitorWrapperChain, methodRegistry, modifiers, typeAttributeAppender, methodLookupEngineFactory, defaultFieldAttributeAppenderFactory, defaultMethodAttributeAppenderFactory, methodMatcher, nonNull(instrumentation), MethodAttributeAppender.NoOp.INSTANCE); } @Override public MethodAnnotationTarget withoutCode() { return intercept(Instrumentation.ForAbstractMethod.INSTANCE); } /** * Returns the outer class instance of this instance. * * @return The outer class instance. */ private ByteBuddy getByteBuddy() { return ByteBuddy.this; } @Override public boolean equals(Object other) { return this == other || !(other == null || getClass() != other.getClass()) && ByteBuddy.this.equals(((MatchedMethodInterception) other).getByteBuddy()) && methodMatcher.equals(((MatchedMethodInterception) other).methodMatcher); } @Override public int hashCode() { return 31 * methodMatcher.hashCode() + ByteBuddy.this.hashCode(); } @Override public String toString() { return "ByteBuddy.MatchedMethodInterception{" + "methodMatcher=" + methodMatcher + "byteBuddy=" + ByteBuddy.this.toString() + '}'; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy