ParameterNameDiscoverer implementation that tries to deduce parameter names
for an advice method from the pointcut expression, returning, and throwing clauses.
If an unambiguous interpretation is not available, it returns null.
If an unambiguous binding can be deduced, then it is.
If the advice requirements cannot possibly be satisfied, then null
is returned. By setting the raiseExceptions
property to true, descriptive exceptions will be thrown instead of
returning null in the case that the parameter names cannot be discovered.
This class interprets arguments in the following way:
JoinPoint
or ProceedingJoinPoint, it is assumed to be for passing
thisJoinPoint to the advice, and the parameter name will
be assigned the value "thisJoinPoint".JoinPoint.StaticPart, it is assumed to be for passing
"thisJoinPointStaticPart" to the advice, and the parameter name
will be assigned the value "thisJoinPointStaticPart".throwingName has been set, and
there are no unbound arguments of type Throwable+, then an
IllegalArgumentException is raised. If there is more than one
unbound argument of type Throwable+, then an
AmbiguousBindingException is raised. If there is exactly one
unbound argument of type Throwable+, then the corresponding
parameter name is assigned the value <throwingName>.a be the number of annotation-based pointcut
expressions (@annotation, @this, @target, @args,
@within, @withincode) that are used in binding form. Usage in
binding form has itself to be deduced: if the expression inside the
pointcut is a single string literal that meets Java variable name
conventions it is assumed to be a variable name. If a is
zero we proceed to the next stage. If a > 1 then an
AmbiguousBindingException is raised. If a == 1,
and there are no unbound arguments of type Annotation+,
then an IllegalArgumentException is raised. If there is
exactly one such argument, then the corresponding parameter name is
assigned the value from the pointcut expression.returningName has been set, and there are no unbound arguments
then an IllegalArgumentException is raised. If there is
more than one unbound argument then an
AmbiguousBindingException is raised. If there is exactly
one unbound argument then the corresponding parameter name is assigned
the value of the returningName.this, target, and
args pointcut expressions used in the binding form (binding
forms are deduced as described for the annotation based pointcuts). If
there remains more than one unbound argument of a primitive type (which
can only be bound in args) then an
AmbiguousBindingException is raised. If there is exactly
one argument of a primitive type, then if exactly one args
bound variable was found, we assign the corresponding parameter name
the variable name. If there were no args bound variables
found an IllegalStateException is raised. If there are
multiple args bound variables, an
AmbiguousBindingException is raised. At this point, if
there remains more than one unbound argument we raise an
AmbiguousBindingException. If there are no unbound arguments
remaining, we are done. If there is exactly one unbound argument
remaining, and only one candidate variable name unbound from
this, target, or args, it is
assigned as the corresponding parameter name. If there are multiple
possibilities, an AmbiguousBindingException is raised.The behavior on raising an IllegalArgumentException or
AmbiguousBindingException is configurable to allow this discoverer
to be used as part of a chain-of-responsibility. By default the condition will
be logged and the getParameterNames(Method) method will simply return
null. If the raiseExceptions
property is set to true, the conditions will be thrown as
IllegalArgumentException and AmbiguousBindingException,
respectively.
| Modifier and Type | Class and Description |
|---|---|
| public static class | AspectJAdviceParameterNameDiscoverer.
Thrown in response to an ambiguous binding being detected when trying to resolve a method's parameter names. |
| private static record | AspectJAdviceParameterNameDiscoverer.
Simple record to hold the extracted text from a pointcut body, together with the number of tokens consumed in extracting it. |
| Modifier and Type | Field and Description |
|---|---|
| private Class | |
| private static final Set | |
| private int | |
| private String[] | |
| private final String | pointcutExpression
The pointcut expression associated with the advice, as a simple String. |
| private boolean | |
| private String | returningName
If the advice is afterReturning, and binds the return value, this is the parameter name used. |
| private static final Set | |
| private static final int | |
| private static final int | |
| private static final int | |
| private static final int | |
| private static final int | |
| private static final int | |
| private static final int | |
| private static final int | |
| private static final String | |
| private static final String | |
| private String | throwingName
If the advice is afterThrowing, and binds the thrown value, this is the parameter name used. |
| Access | Constructor and Description |
|---|---|
| public | AspectJAdviceParameterNameDiscoverer(String pointcutExpression)
Create a new discoverer that attempts to discover parameter names. |
| Modifier and Type | Method and Description |
|---|---|
| private boolean | |
| private void | bindAnnotationsFromVarNames(List<String> varNames)
Match the given list of extracted variable names to argument slots. |
| private void | |
| private int | |
| private int | |
| private void | findAndBind(Class<?> argumentType, String varName)
Find the argument index with the given type, and bind the given
|
| public String[] | Returns: the parameter namesthe target method)MethodImplements org. Deduce the parameter names for an advice method. |
| public String[] | Returns: nullthe constructor to find parameter names for ctor)Implements org. An advice method can never be a constructor in Spring. |
| private AspectJAdviceParameterNameDiscoverer. | getPointcutBody(String[] tokens, int startIndex)
We've found the start of a binding pointcut at the given index into the token array. |
| private boolean | isSubtypeOf(Class<?> supertype, int argumentNumber)
Return |
| private boolean | |
| private void | maybeBindAnnotationsFromPointcutExpression()
Parse the string pointcut expression looking for: @this, @target, @args, @within, @withincode, @annotation. |
| private void | maybeBindPrimitiveArgsFromPointcutExpression()
Match up args against unbound arguments of primitive types. |
| private void | |
| private void | maybeBindReturningVariable()
If a returning variable was specified and there is only one choice remaining, bind it. |
| private boolean | maybeBindThisJoinPoint()
If the first parameter is of type JoinPoint or ProceedingJoinPoint, bind "thisJoinPoint" as parameter name and return true, else return false. |
| private void | |
| private void | maybeBindThisOrTargetOrArgsFromPointcutExpression()
Parse the string pointcut expression looking for this(), target() and args() expressions. |
| private void | maybeBindThrowingVariable()
If a throwing name was specified and there is exactly one choice remaining (argument that is a subtype of Throwable) then bind it. |
| private String | maybeExtractVariableName(String candidateToken)
If the token starts meets Java identifier conventions, it's in. |
| private void | maybeExtractVariableNamesFromArgs(String argsSpec, List<String> varNames)
Given an args pointcut body (could be |
| public void | setRaiseExceptions(boolean
true if exceptions are to be thrownIndicate whether |
| public void | setReturningName(String
the name of the returning variable returningName)If |
| public void | setThrowingName(String
the name of the throwing variable throwingName)If |
| argumentTypes | back to summary |
|---|---|
| private Class<?>[] argumentTypes | |
| nonReferencePointcutTokens | back to summary |
|---|---|
| private static final Set<String> nonReferencePointcutTokens | |
| numberOfRemainingUnboundArguments | back to summary |
|---|---|
| private int numberOfRemainingUnboundArguments | |
| parameterNameBindings | back to summary |
|---|---|
| private String[] parameterNameBindings | |
| pointcutExpression | back to summary |
|---|---|
| private final String pointcutExpression The pointcut expression associated with the advice, as a simple String. | |
| raiseExceptions | back to summary |
|---|---|
| private boolean raiseExceptions | |
| returningName | back to summary |
|---|---|
| private String returningName If the advice is afterReturning, and binds the return value, this is the parameter name used. | |
| singleValuedAnnotationPcds | back to summary |
|---|---|
| private static final Set<String> singleValuedAnnotationPcds | |
| STEP_ANNOTATION_BINDING | back to summary |
|---|---|
| private static final int STEP_ANNOTATION_BINDING | |
| STEP_FINISHED | back to summary |
|---|---|
| private static final int STEP_FINISHED | |
| STEP_JOIN_POINT_BINDING | back to summary |
|---|---|
| private static final int STEP_JOIN_POINT_BINDING | |
| STEP_PRIMITIVE_ARGS_BINDING | back to summary |
|---|---|
| private static final int STEP_PRIMITIVE_ARGS_BINDING | |
| STEP_REFERENCE_PCUT_BINDING | back to summary |
|---|---|
| private static final int STEP_REFERENCE_PCUT_BINDING | |
| STEP_RETURNING_BINDING | back to summary |
|---|---|
| private static final int STEP_RETURNING_BINDING | |
| STEP_THIS_TARGET_ARGS_BINDING | back to summary |
|---|---|
| private static final int STEP_THIS_TARGET_ARGS_BINDING | |
| STEP_THROWING_BINDING | back to summary |
|---|---|
| private static final int STEP_THROWING_BINDING | |
| THIS_JOIN_POINT | back to summary |
|---|---|
| private static final String THIS_JOIN_POINT | |
| THIS_JOIN_POINT_STATIC_PART | back to summary |
|---|---|
| private static final String THIS_JOIN_POINT_STATIC_PART | |
| throwingName | back to summary |
|---|---|
| private String throwingName If the advice is afterThrowing, and binds the thrown value, this is the parameter name used. | |
| AspectJAdviceParameterNameDiscoverer | back to summary |
|---|---|
| public AspectJAdviceParameterNameDiscoverer(String pointcutExpression) Create a new discoverer that attempts to discover parameter names. from the given pointcut expression. | |
| alreadyBound | back to summary |
|---|---|
| private boolean alreadyBound(String varName) | |
| bindAnnotationsFromVarNames | back to summary |
|---|---|
| private void bindAnnotationsFromVarNames(List<String> varNames) Match the given list of extracted variable names to argument slots. | |
| bindParameterName | back to summary |
|---|---|
| private void bindParameterName(int index, String name) | |
| countNumberOfUnboundAnnotationArguments | back to summary |
|---|---|
| private int countNumberOfUnboundAnnotationArguments() | |
| countNumberOfUnboundPrimitiveArguments | back to summary |
|---|---|
| private int countNumberOfUnboundPrimitiveArguments() | |
| findAndBind | back to summary |
|---|---|
| private void findAndBind(Class<?> argumentType, String varName) Find the argument index with the given type, and bind the given
| |
| getParameterNames | back to summary |
|---|---|
| public String[] getParameterNames(Method method) Implements org. Deduce the parameter names for an advice method. See the | |
| getParameterNames | back to summary |
|---|---|
| public String[] getParameterNames(Constructor<?> ctor) Implements org. An advice method can never be a constructor in Spring.
| |
| getPointcutBody | back to summary |
|---|---|
| private AspectJAdviceParameterNameDiscoverer. We've found the start of a binding pointcut at the given index into the token array. Now we need to extract the pointcut body and return it. | |
| isSubtypeOf | back to summary |
|---|---|
| private boolean isSubtypeOf(Class<?> supertype, int argumentNumber) Return | |
| isUnbound | back to summary |
|---|---|
| private boolean isUnbound(int i) | |
| maybeBindAnnotationsFromPointcutExpression | back to summary |
|---|---|
| private void maybeBindAnnotationsFromPointcutExpression() Parse the string pointcut expression looking for: @this, @target, @args, @within, @withincode, @annotation. If we find one of these pointcut expressions, try and extract a candidate variable name (or variable names, in the case of args). Some more support from AspectJ in doing this exercise would be nice... :) | |
| maybeBindPrimitiveArgsFromPointcutExpression | back to summary |
|---|---|
| private void maybeBindPrimitiveArgsFromPointcutExpression() Match up args against unbound arguments of primitive types. | |
| maybeBindReferencePointcutParameter | back to summary |
|---|---|
| private void maybeBindReferencePointcutParameter() | |
| maybeBindReturningVariable | back to summary |
|---|---|
| private void maybeBindReturningVariable() If a returning variable was specified and there is only one choice remaining, bind it. | |
| maybeBindThisJoinPoint | back to summary |
|---|---|
| private boolean maybeBindThisJoinPoint() If the first parameter is of type JoinPoint or ProceedingJoinPoint, bind "thisJoinPoint" as parameter name and return true, else return false. | |
| maybeBindThisJoinPointStaticPart | back to summary |
|---|---|
| private void maybeBindThisJoinPointStaticPart() | |
| maybeBindThisOrTargetOrArgsFromPointcutExpression | back to summary |
|---|---|
| private void maybeBindThisOrTargetOrArgsFromPointcutExpression() Parse the string pointcut expression looking for this(), target() and args() expressions. If we find one, try and extract a candidate variable name and bind it. | |
| maybeBindThrowingVariable | back to summary |
|---|---|
| private void maybeBindThrowingVariable() If a throwing name was specified and there is exactly one choice remaining (argument that is a subtype of Throwable) then bind it. | |
| maybeExtractVariableName | back to summary |
|---|---|
| private String maybeExtractVariableName(String candidateToken) If the token starts meets Java identifier conventions, it's in.
| |
| maybeExtractVariableNamesFromArgs | back to summary |
|---|---|
| private void maybeExtractVariableNamesFromArgs(String argsSpec, List<String> varNames) Given an args pointcut body (could be | |
| setRaiseExceptions | back to summary |
|---|---|
| public void setRaiseExceptions(boolean raiseExceptions) Indicate whether
| |
| setReturningName | back to summary |
|---|---|
| public void setReturningName(String returningName) If
| |
| setThrowingName | back to summary |
|---|---|
| public void setThrowingName(String throwingName) If
| |
| Access | Constructor and Description |
|---|---|
| public | AmbiguousBindingException(String
the detail message msg)Construct a new AmbiguousBindingException with the specified message. |
| AmbiguousBindingException | back to summary |
|---|---|
| public AmbiguousBindingException(String msg) Construct a new AmbiguousBindingException with the specified message.
| |
| Modifier and Type | Field and Description |
|---|---|
| private final int | numTokensConsumed
Record Component accessed by numTokensConsumed(). |
| private final String |
| Access | Constructor and Description |
|---|---|
| private |
| Modifier and Type | Method and Description |
|---|---|
| public final boolean | equals(Object
the reference object with which to compare. o)Implements abstract java. Indicates whether some other object is "equal to" this one. |
| public final int | |
| public int | |
| public String | |
| public final String | toString()
Implements abstract java. Returns a string representation of the record. |
| numTokensConsumed | back to summary |
|---|---|
| private final int numTokensConsumed Record Component accessed by numTokensConsumed(). | |
| text | back to summary |
|---|---|
| private final String text Record Component accessed by text(). | |
| PointcutBody | back to summary |
|---|---|
| private PointcutBody(int numTokensConsumed, String text) | |
| equals | back to summary |
|---|---|
| public final boolean equals(Object o) Implements abstract java. Doc from java. Indicates whether some other object is "equal to" this one. In addition
to the general contract of
R copy = new R(r.c1(), r.c2(), ..., r.cn());
then it must be the case that r.equals(copy).
| |
| hashCode | back to summary |
|---|---|
| public final int hashCode() Implements abstract java. Doc from java. Returns a hash code value for the record.
Obeys the general contract of
| |
| numTokensConsumed | back to summary |
|---|---|
| public int numTokensConsumed() Record Component getter of numTokensConsumed. | |
| text | back to summary |
|---|---|
| public String text() Record Component getter of text.
| |
| toString | back to summary |
|---|---|
| public final String toString() Implements abstract java. Doc from java. Returns a string representation of the record.
In accordance with the general contract of In addition to this general contract, record classes must further participate in the invariant that any two records which are equal must produce equal strings. This invariant is necessarily relaxed in the rare case where corresponding equal component values might fail to produce equal strings for themselves.
| |