|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object org.springframework.aop.aspectj.AspectJAdviceParameterNameDiscoverer
public class AspectJAdviceParameterNameDiscoverer
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
.
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
AspectJAdviceParameterNameDiscoverer.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.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 <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 will simply return
null
. If the raiseExceptions
property is set to true
, the conditions will be thrown as
IllegalArgumentException
and AmbiguousBindingException
,
respectively.
Was that perfectly clear? ;)
Short version: 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.
Nested Class Summary | |
---|---|
static class |
AspectJAdviceParameterNameDiscoverer.AmbiguousBindingException
Thrown in response to an ambiguous binding being detected when trying to resolve a method's parameter names. |
private static class |
AspectJAdviceParameterNameDiscoverer.PointcutBody
Simple struct to hold the extracted text from a pointcut body, together with the number of tokens consumed in extracting it. |
Field Summary | |
---|---|
private java.lang.Class[] |
argumentTypes
|
private static java.util.Set<java.lang.String> |
nonReferencePointcutTokens
|
private int |
numberOfRemainingUnboundArguments
|
private java.lang.String[] |
parameterNameBindings
|
private java.lang.String |
pointcutExpression
The pointcut expression associated with the advice, as a simple String. |
private boolean |
raiseExceptions
|
private java.lang.String |
returningName
If the advice is afterReturning, and binds the return value, this is the parameter name used. |
private static java.util.Set<java.lang.String> |
singleValuedAnnotationPcds
|
private static int |
STEP_ANNOTATION_BINDING
|
private static int |
STEP_FINISHED
|
private static int |
STEP_JOIN_POINT_BINDING
|
private static int |
STEP_PRIMITIVE_ARGS_BINDING
|
private static int |
STEP_REFERENCE_PCUT_BINDING
|
private static int |
STEP_RETURNING_BINDING
|
private static int |
STEP_THIS_TARGET_ARGS_BINDING
|
private static int |
STEP_THROWING_BINDING
|
private static java.lang.String |
THIS_JOIN_POINT
|
private static java.lang.String |
THIS_JOIN_POINT_STATIC_PART
|
private java.lang.String |
throwingName
If the advice is afterThrowing, and binds the thrown value, this is the parameter name used. |
Constructor Summary | |
---|---|
AspectJAdviceParameterNameDiscoverer(java.lang.String pointcutExpression)
Create a new discoverer that attempts to discover parameter names from the given pointcut expression. |
Method Summary | |
---|---|
private boolean |
alreadyBound(java.lang.String varName)
|
private void |
bindAnnotationsFromVarNames(java.util.List<java.lang.String> varNames)
Match the given list of extracted variable names to argument slots. |
private void |
bindParameterName(int index,
java.lang.String name)
|
private int |
countNumberOfUnboundAnnotationArguments()
|
private int |
countNumberOfUnboundPrimitiveArguments()
|
private void |
findAndBind(java.lang.Class argumentType,
java.lang.String varName)
|
java.lang.String[] |
getParameterNames(java.lang.reflect.Constructor ctor)
An advice method can never be a constructor in Spring. |
java.lang.String[] |
getParameterNames(java.lang.reflect.Method method)
Deduce the parameter names for an advice method. |
private AspectJAdviceParameterNameDiscoverer.PointcutBody |
getPointcutBody(java.lang.String[] tokens,
int startIndex)
|
private boolean |
isSubtypeOf(java.lang.Class supertype,
int argumentNumber)
|
private boolean |
isUnbound(int i)
|
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 |
maybeBindReferencePointcutParameter()
|
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 |
maybeBindThisJoinPointStaticPart()
|
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 java.lang.String |
maybeExtractVariableName(java.lang.String candidateToken)
|
private void |
maybeExtractVariableNamesFromArgs(java.lang.String argsSpec,
java.util.List<java.lang.String> varNames)
Given an args pointcut body (could be args or at_args ),
add any candidate variable names to the given list. |
void |
setRaiseExceptions(boolean raiseExceptions)
Indicate whether IllegalArgumentException and AspectJAdviceParameterNameDiscoverer.AmbiguousBindingException
must be thrown as appropriate in the case of failing to deduce advice parameter names. |
void |
setReturningName(java.lang.String returningName)
If afterReturning advice binds the return value, the
returning variable name must be specified. |
void |
setThrowingName(java.lang.String throwingName)
If afterThrowing advice binds the thrown value, the
throwing variable name must be specified. |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Field Detail |
---|
private static final java.lang.String THIS_JOIN_POINT
private static final java.lang.String THIS_JOIN_POINT_STATIC_PART
private static final int STEP_JOIN_POINT_BINDING
private static final int STEP_THROWING_BINDING
private static final int STEP_ANNOTATION_BINDING
private static final int STEP_RETURNING_BINDING
private static final int STEP_PRIMITIVE_ARGS_BINDING
private static final int STEP_THIS_TARGET_ARGS_BINDING
private static final int STEP_REFERENCE_PCUT_BINDING
private static final int STEP_FINISHED
private static final java.util.Set<java.lang.String> singleValuedAnnotationPcds
private static final java.util.Set<java.lang.String> nonReferencePointcutTokens
private boolean raiseExceptions
private java.lang.String returningName
private java.lang.String throwingName
private java.lang.String pointcutExpression
private java.lang.Class[] argumentTypes
private java.lang.String[] parameterNameBindings
private int numberOfRemainingUnboundArguments
Constructor Detail |
---|
public AspectJAdviceParameterNameDiscoverer(java.lang.String pointcutExpression)
Method Detail |
---|
public void setRaiseExceptions(boolean raiseExceptions)
IllegalArgumentException
and AspectJAdviceParameterNameDiscoverer.AmbiguousBindingException
must be thrown as appropriate in the case of failing to deduce advice parameter names.
raiseExceptions
- true
if exceptions are to be thrownpublic void setReturningName(java.lang.String returningName)
afterReturning
advice binds the return value, the
returning variable name must be specified.
returningName
- the name of the returning variablepublic void setThrowingName(java.lang.String throwingName)
afterThrowing
advice binds the thrown value, the
throwing variable name must be specified.
throwingName
- the name of the throwing variablepublic java.lang.String[] getParameterNames(java.lang.reflect.Method method)
See the class level javadoc
for this class for details of the algorithm used.
getParameterNames
in interface ParameterNameDiscoverer
method
- the target Method
public java.lang.String[] getParameterNames(java.lang.reflect.Constructor ctor)
getParameterNames
in interface ParameterNameDiscoverer
ctor
- constructor to find parameter names for
null
java.lang.UnsupportedOperationException
- if
raiseExceptions
has been set to true
private void bindParameterName(int index, java.lang.String name)
private boolean maybeBindThisJoinPoint()
private void maybeBindThisJoinPointStaticPart()
private void maybeBindThrowingVariable()
private void maybeBindReturningVariable()
private void maybeBindAnnotationsFromPointcutExpression()
Some more support from AspectJ in doing this exercise would be nice... :)
private void bindAnnotationsFromVarNames(java.util.List<java.lang.String> varNames)
private java.lang.String maybeExtractVariableName(java.lang.String candidateToken)
private void maybeExtractVariableNamesFromArgs(java.lang.String argsSpec, java.util.List<java.lang.String> varNames)
args
or at_args
),
add any candidate variable names to the given list.
private void maybeBindThisOrTargetOrArgsFromPointcutExpression()
private void maybeBindReferencePointcutParameter()
private AspectJAdviceParameterNameDiscoverer.PointcutBody getPointcutBody(java.lang.String[] tokens, int startIndex)
private void maybeBindPrimitiveArgsFromPointcutExpression()
private boolean isUnbound(int i)
private boolean alreadyBound(java.lang.String varName)
private boolean isSubtypeOf(java.lang.Class supertype, int argumentNumber)
private int countNumberOfUnboundAnnotationArguments()
private int countNumberOfUnboundPrimitiveArguments()
private void findAndBind(java.lang.Class argumentType, java.lang.String varName)
|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |