org.springframework.aop.aspectj

## Class AspectJAdviceParameterNameDiscoverer

- java.lang.Object
- - org.springframework.aop.aspectj.AspectJAdviceParameterNameDiscoverer

- All Implemented Interfaces:
    ParameterNameDiscoverer

      public class AspectJAdviceParameterNameDiscoverer
      extends Object
      implements 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`.

  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.

  Since:
    2.0
  Author:
    Adrian Colyer

- - ### Nested Class Summary

    Nested Classes
    Modifier and Type | Class and Description
    --- | ---
    `static class` | `AspectJAdviceParameterNameDiscoverer.AmbiguousBindingException` Thrown in response to an ambiguous binding being detected when trying to resolve a method's parameter names.

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `AspectJAdviceParameterNameDiscoverer(String pointcutExpression)` Create a new discoverer that attempts to discover parameter names from the given pointcut expression.

  - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `String[]` | `getParameterNames(Constructor ctor)` An advice method can never be a constructor in Spring.
    `String[]` | `getParameterNames(Method method)` Deduce the parameter names for an advice method.
    `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(String returningName)` If `afterReturning` advice binds the return value, the returning variable name must be specified.
    `void` | `setThrowingName(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`

- - ### Constructor Detail

    - #### AspectJAdviceParameterNameDiscoverer

          public AspectJAdviceParameterNameDiscoverer(String pointcutExpression)

      Create a new discoverer that attempts to discover parameter names from the given pointcut expression.

  - ### Method Detail

    - #### 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.
      Parameters:
        `raiseExceptions` - `true` if exceptions are to be thrown

    - #### setReturningName

          public void setReturningName(String returningName)

      If `afterReturning` advice binds the return value, the returning variable name must be specified.
      Parameters:
        `returningName` - the name of the returning variable

    - #### setThrowingName

          public void setThrowingName(String throwingName)

      If `afterThrowing` advice binds the thrown value, the throwing variable name must be specified.
      Parameters:
        `throwingName` - the name of the throwing variable

    - #### getParameterNames

          public String[] getParameterNames(Method method)

      Deduce the parameter names for an advice method.

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

      Specified by:
        `getParameterNames` in interface `ParameterNameDiscoverer`
      Parameters:
        `method` - the target `Method`
      Returns:
        the parameter names

    - #### getParameterNames

          public String[] getParameterNames(Constructor ctor)

      An advice method can never be a constructor in Spring.
      Specified by:
        `getParameterNames` in interface `ParameterNameDiscoverer`
      Parameters:
        `ctor` - constructor to find parameter names for
      Returns:
        `null`
      Throws:
        `UnsupportedOperationException` - if `raiseExceptions` has been set to `true`