/**
* Matches {@link MethodDescription}s that return a given erasure type.
* @param type The raw type the matched method is expected to return.
* @param <T> The type of the matched object.
* @return An element matcher that matches a given return type for a method description.
public static <T extends MethodDescription> ElementMatcher.Junction<T> returns(TypeDescription type) {
return returns(is(type));
/**
* Matches any Java bean getter method.
* @param <T> The type of the matched object.
* @return A matcher that matches any getter method.
public static <T extends MethodDescription> ElementMatcher.Junction<T> isGetter() {
return takesArguments(0).and(not(returns(TypeDescription.VOID))).and(nameStartsWith("get").or(nameStartsWith("is").and(returnsGeneric(anyOf(boolean.class, Boolean.class)))));
/**
* Matches any Java bean setter method.
* @param <T> The type of the matched object.
* @return A matcher that matches any setter method.
public static <T extends MethodDescription> ElementMatcher.Junction<T> isSetter() {
return nameStartsWith("set").and(takesArguments(1)).and(returns(TypeDescription.VOID));
/**
* Only matches the {@link Object#finalize()} method, even if it was overridden.
* @param <T> The type of the matched object.
* @return A matcher that only matches the {@link Object#finalize()} method.
public static <T extends MethodDescription> ElementMatcher.Junction<T> isFinalizer() {
return named("finalize").and(takesArguments(0)).and(returns(TypeDescription.VOID));
/**
* Only matches the {@link Object#toString()} method, also if it was overridden.
* @param <T> The type of the matched object.
* @return A matcher that only matches the {@link Object#toString()} method.
public static <T extends MethodDescription> ElementMatcher.Junction<T> isHashCode() {
return named("hashCode").and(takesArguments(0)).and(returns(int.class));
/**
* Only matches the {@link Object#equals(Object)} method, also if it was overridden.
* @param <T> The type of the matched object.
* @return A matcher that only matches the {@link Object#equals(Object)} method.
public static <T extends MethodDescription> ElementMatcher.Junction<T> isEquals() {
return named("equals").and(takesArguments(TypeDescription.OBJECT)).and(returns(boolean.class));
/**
* Only matches the {@link Object#toString()} method, also if it was overridden.
* @param <T> The type of the matched object.
* @return A matcher that only matches the {@link Object#toString()} method.
public static <T extends MethodDescription> ElementMatcher.Junction<T> isToString() {
return named("toString").and(takesArguments(0)).and(returns(TypeDescription.STRING));
@Override protected ElementMatcher.Junction<MethodDescription> getExtraMethodElementMatcher() { return named("getHandler").and(returns(named("org.springframework.web.servlet.HandlerExecutionChain")));
@Override protected ElementMatcher.Junction<MethodDescription> getMethodElementMatcher() { return named("postProcessBeforeInitialization") .and(returns(Object.class)) .and(takesArguments(Object.class, String.class));
@Override protected ElementMatcher.Junction<MethodDescription> getExtraMethodElementMatcher() { return named("getPort").or(named("createDispatch").and(returns(named("javax.xml.ws.Dispatch"))));
private ProxyDefinitionHelpers() {
this.groovyGetMetaClassFilter = isSynthetic().and( named( "getMetaClass" )
.and( returns( td -> "groovy.lang.MetaClass".equals( td.getName() ) ) ) );
this.virtualNotFinalizerFilter = isVirtual().and( not( isFinalizer() ) );
this.hibernateGeneratedMethodFilter = nameStartsWith( "$$_hibernate_" ).and( isVirtual() );
PrivilegedAction<MethodDelegation> delegateToInterceptorDispatcherMethodDelegationPrivilegedAction =
new PrivilegedAction<MethodDelegation>() {
@Override
public MethodDelegation run() {
return MethodDelegation.to( ProxyConfiguration.InterceptorDispatcher.class );
this.delegateToInterceptorDispatcherMethodDelegation = System.getSecurityManager() != null
? AccessController.doPrivileged( delegateToInterceptorDispatcherMethodDelegationPrivilegedAction )
: delegateToInterceptorDispatcherMethodDelegationPrivilegedAction.run();
PrivilegedAction<FieldAccessor.PropertyConfigurable> interceptorFieldAccessorPrivilegedAction =
new PrivilegedAction<FieldAccessor.PropertyConfigurable>() {
@Override
public FieldAccessor.PropertyConfigurable run() {
return FieldAccessor.ofField( ProxyConfiguration.INTERCEPTOR_FIELD_NAME )
.withAssigner( Assigner.DEFAULT, Assigner.Typing.DYNAMIC );
this.interceptorFieldAccessor = System.getSecurityManager() != null
? AccessController.doPrivileged( interceptorFieldAccessorPrivilegedAction )
: interceptorFieldAccessorPrivilegedAction.run();
@Override protected ElementMatcher.Junction<MethodDescription> getExtraMethodElementMatcher() { return named("getConnection") .and(returns(Connection.class)) .and(isPublic()) .and(takesArguments(String.class, String.class).or(takesArguments(0)));
/**
* {@inheritDoc}
public ByteCodeAppender appender(Target implementationTarget) {
return new Appender(targetMethod.getOwnerType()
.getDeclaredMethods()
.filter(hasMethodName(targetMethod.getName())
.and(returns(targetMethod.getReturnType()))
.and(takesArguments(targetMethod.getParameterTypes())))
.getOnly(),
specializedLambdaMethod,
implementationTarget.getInstrumentedType().getDeclaredFields());
.or(returns(isPackagePrivate()))
.or(hasParameters(whereAny(hasType(isPackagePrivate())))));
.and(returns(isVisibleTo(instrumentedType)))
.and(hasParameters(whereNone(hasType(not(isVisibleTo(instrumentedType))))))
.and(ignoredMethods.resolve(instrumentedType));
/**
* {@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);
/**
* Creates a matcher where only overridable or declared methods are matched unless those are ignored. Methods that
* are declared by the target type are only matched if they are not ignored. Declared methods that are not found on the
* target type are always matched.
* @param ignoredMethods A method matcher that matches any ignored method.
* @param originalType The original type of the instrumentation before adding any user methods.
* @return A latent method matcher that identifies any method to instrument for a rebasement or redefinition.
protected static LatentMatcher<MethodDescription> of(LatentMatcher<? super MethodDescription> ignoredMethods, TypeDescription originalType) {
ElementMatcher.Junction<MethodDescription> predefinedMethodSignatures = none();
for (MethodDescription methodDescription : originalType.getDeclaredMethods()) {
ElementMatcher.Junction<MethodDescription> signature = methodDescription.isConstructor()
? isConstructor()
: ElementMatchers.<MethodDescription>named(methodDescription.getName());
signature = signature.and(returns(methodDescription.getReturnType().asErasure()));
signature = signature.and(takesArguments(methodDescription.getParameters().asTypeList().asErasures()));
predefinedMethodSignatures = predefinedMethodSignatures.or(signature);
return new InliningImplementationMatcher(ignoredMethods, predefinedMethodSignatures);
@Override public boolean matches(TypeDescription targetInterface) { if (ElementMatchers.declaresMethod(named(targetMethod.getName()) .and(returns(targetMethod.getReturnType().asErasure())) .and(takesArguments(targetMethod.getParameters().asTypeList().asErasures()))) .matches(targetInterface)) { return true; } else { for (TypeDescription typeDescription : targetInterface.getInterfaces().asErasures()) { if (matches(typeDescription)) { return true; return false;
@Override public boolean matches(MethodDescription targetMethod) { TypeDescription superClass = targetMethod.getDeclaringType().asErasure(); superClass = superClass.getSuperClass().asErasure(); if (declaresMethod(named(targetMethod.getName()) .and(returns(targetMethod.getReturnType().asErasure())) .and(takesArguments(targetMethod.getParameters().asTypeList().asErasures())) .and(extraMethodMatcher)) .matches(superClass)) { return true; } while (superClassMatcher.matches(superClass)); return false;
.method(named(lambdaMethodName)
.and(takesArguments(lambdaMethod.getParameterTypes()))
.and(returns(lambdaMethod.getReturnType())))
.intercept(new LambdaMethodImplementation(targetMethod, specializedLambdaMethod));
int index = 0;