类 AspectJAdviceParameterNameDiscoverer

java.lang.Object
infra.core.ParameterNameDiscoverer
infra.aop.aspectj.AspectJAdviceParameterNameDiscoverer

public class AspectJAdviceParameterNameDiscoverer extends infra.core.ParameterNameDiscoverer
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.

Algorithm Summary

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.

Algorithm Details

This class interprets arguments in the following way:

  1. If the first parameter of the method is of type JoinPoint or ProceedingJoinPoint, it is assumed to be for passing thisJoinPoint to the advice, and the parameter name will be assigned the value "thisJoinPoint".
  2. If the first parameter of the method is of type JoinPoint.StaticPart, it is assumed to be for passing "thisJoinPointStaticPart" to the advice, and the parameter name will be assigned the value "thisJoinPointStaticPart".
  3. If a 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>.
  4. If there remain unbound arguments, then the pointcut expression is examined. Let 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.
  5. If a 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 <returningName>.
  6. If there remain unbound arguments, then the pointcut expression is examined once more for 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.

从以下版本开始:
4.0
作者:
Adrian Colyer, Juergen Hoeller
  • 字段详细资料

    • THIS_JOIN_POINT

      private static final String THIS_JOIN_POINT
      另请参阅:
    • THIS_JOIN_POINT_STATIC_PART

      private static final String THIS_JOIN_POINT_STATIC_PART
      另请参阅:
    • STEP_JOIN_POINT_BINDING

      private static final int STEP_JOIN_POINT_BINDING
      另请参阅:
    • STEP_THROWING_BINDING

      private static final int STEP_THROWING_BINDING
      另请参阅:
    • STEP_ANNOTATION_BINDING

      private static final int STEP_ANNOTATION_BINDING
      另请参阅:
    • STEP_RETURNING_BINDING

      private static final int STEP_RETURNING_BINDING
      另请参阅:
    • STEP_PRIMITIVE_ARGS_BINDING

      private static final int STEP_PRIMITIVE_ARGS_BINDING
      另请参阅:
    • STEP_THIS_TARGET_ARGS_BINDING

      private static final int STEP_THIS_TARGET_ARGS_BINDING
      另请参阅:
    • STEP_REFERENCE_PCUT_BINDING

      private static final int STEP_REFERENCE_PCUT_BINDING
      另请参阅:
    • STEP_FINISHED

      private static final int STEP_FINISHED
      另请参阅:
    • singleValuedAnnotationPcds

      private static final Set<String> singleValuedAnnotationPcds
    • nonReferencePointcutTokens

      private static final Set<String> nonReferencePointcutTokens
    • pointcutExpression

      @Nullable private final String pointcutExpression
      The pointcut expression associated with the advice, as a simple String.
    • raiseExceptions

      private boolean raiseExceptions
    • returningName

      @Nullable private String returningName
      If the advice is afterReturning, and binds the return value, this is the parameter name used.
    • throwingName

      @Nullable private String throwingName
      If the advice is afterThrowing, and binds the thrown value, this is the parameter name used.
    • argumentTypes

      private Class<?>[] argumentTypes
    • parameterNameBindings

      private String[] parameterNameBindings
    • numberOfRemainingUnboundArguments

      private int numberOfRemainingUnboundArguments
  • 构造器详细资料

    • AspectJAdviceParameterNameDiscoverer

      public AspectJAdviceParameterNameDiscoverer(@Nullable String pointcutExpression)
      Create a new discoverer that attempts to discover parameter names. from the given pointcut expression.
  • 方法详细资料

    • setRaiseExceptions

      public 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.
      参数:
      raiseExceptions - true if exceptions are to be thrown
    • setReturningName

      public void setReturningName(@Nullable String returningName)
      If afterReturning advice binds the return value, the returning variable name must be specified.
      参数:
      returningName - the name of the returning variable
    • setThrowingName

      public void setThrowingName(@Nullable String throwingName)
      If afterThrowing advice binds the thrown value, the throwing variable name must be specified.
      参数:
      throwingName - the name of the throwing variable
    • getParameterNames

      @Nullable public String[] getParameterNames(@Nullable Executable method)
      Deduce the parameter names for an advice method.

      See the class level javadoc for this class for details of the algorithm used.

      覆盖:
      getParameterNames 在类中 infra.core.ParameterNameDiscoverer
      参数:
      method - the target Method
      返回:
      the parameter names
    • bindParameterName

      private void bindParameterName(int index, String name)
    • maybeBindThisJoinPoint

      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

      private void maybeBindThisJoinPointStaticPart()
    • maybeBindThrowingVariable

      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.
    • maybeBindReturningVariable

      private void maybeBindReturningVariable()
      If a returning variable was specified and there is only one choice remaining, bind it.
    • maybeBindAnnotationsFromPointcutExpression

      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... :)

    • bindAnnotationsFromVarNames

      private void bindAnnotationsFromVarNames(List<String> varNames)
      Match the given list of extracted variable names to argument slots.
    • maybeExtractVariableName

      @Nullable private String maybeExtractVariableName(@Nullable String candidateToken)
    • maybeExtractVariableNamesFromArgs

      private void maybeExtractVariableNamesFromArgs(@Nullable String argsSpec, List<String> varNames)
      Given an args pointcut body (could be args or at_args), add any candidate variable names to the given list.
    • maybeBindThisOrTargetOrArgsFromPointcutExpression

      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.
    • maybeBindReferencePointcutParameter

      private void maybeBindReferencePointcutParameter()
    • getPointcutBody

      private AspectJAdviceParameterNameDiscoverer.PointcutBody getPointcutBody(String[] tokens, int startIndex)
    • maybeBindPrimitiveArgsFromPointcutExpression

      private void maybeBindPrimitiveArgsFromPointcutExpression()
      Match up args against unbound arguments of primitive types.
    • isUnbound

      private boolean isUnbound(int i)
    • alreadyBound

      private boolean alreadyBound(String varName)
    • isSubtypeOf

      private boolean isSubtypeOf(Class<?> supertype, int argumentNumber)
    • countNumberOfUnboundAnnotationArguments

      private int countNumberOfUnboundAnnotationArguments()
    • countNumberOfUnboundPrimitiveArguments

      private int countNumberOfUnboundPrimitiveArguments()
    • findAndBind

      private void findAndBind(Class<?> argumentType, String varName)