Update documentation for @AspectJ argument name resolution algorithm
Closes gh-30026
This commit is contained in:
parent
9d28fe90f5
commit
244c97993b
|
@ -1526,17 +1526,54 @@ check the type of the elements.
|
|||
[[aop-ataspectj-advice-params-names]]
|
||||
===== Determining Argument Names
|
||||
|
||||
The parameter binding in advice invocations relies on matching names used in pointcut
|
||||
expressions to declared parameter names in advice and pointcut method signatures.
|
||||
Parameter names are not available through Java reflection, so Spring AOP uses the
|
||||
following strategy to determine parameter names:
|
||||
Parameter binding in advice invocations relies on matching the names used in pointcut
|
||||
expressions to the parameter names declared in advice and pointcut method signatures.
|
||||
|
||||
NOTE: This section uses the terms _argument_ and _parameter_ interchangeably, since
|
||||
AspectJ APIs refer to parameter names as argument names.
|
||||
|
||||
Spring AOP uses the following `ParameterNameDiscoverer` implementations to determine
|
||||
parameter names. Each discoverer will be given a chance to discover parameter names, and
|
||||
the first successful discoverer wins. If none of the registered discoverers is capable
|
||||
of determining parameter names, an `IllegalArgumentException` is thrown.
|
||||
|
||||
|
||||
`KotlinReflectionParameterNameDiscoverer` :: Uses Kotlin reflection APIs if such APIs are
|
||||
present on the classpath.
|
||||
`StandardReflectionParameterNameDiscoverer` :: Uses the `java.lang.reflect.Parameter` API
|
||||
available since Java 8. Requires that code be compiled with the `-parameters` flag for
|
||||
`javac`. Recommended approach on Java 8+.
|
||||
`LocalVariableTableParameterNameDiscoverer` :: Analyzes the local variable table available
|
||||
in the byte code to determine parameter names from debug information. Requires that
|
||||
code be compiled with debug symbols (`-g:vars` at a minimum). Deprecated as of Spring
|
||||
Framework 6.0 for removal in Spring Framework 6.1 in favor of compiling code with
|
||||
`-parameters`. Not supported in a GraalVM native image.
|
||||
`AspectJAdviceParameterNameDiscoverer` :: Uses parameter names that have been explicitly
|
||||
specified by the user via the `argNames` attribute in the corresponding advice or
|
||||
pointcut annotation. See the following section for details.
|
||||
|
||||
[[aop-ataspectj-advice-params-names-explicit]]
|
||||
===== Explicit Argument Names
|
||||
|
||||
@AspectJ advice and pointcut annotations have an optional `argNames` attribute that you
|
||||
can use to specify the argument names of the annotated method. Note, however, that
|
||||
explicit `argNames` will only be used by Spring as a fallback if none of the other
|
||||
`ParameterNameDiscoverer` implementations is able to determine parameter names (see the
|
||||
previous section for details).
|
||||
|
||||
[TIP]
|
||||
====
|
||||
If an @AspectJ aspect has been compiled by the AspectJ compiler (`ajc`) even without
|
||||
debug information, you do not need to add the `argNames` attribute, since the compiler
|
||||
retains the needed information.
|
||||
|
||||
Similarly, if an @AspectJ aspect has been compiled with `javac` using the `-parameters`
|
||||
flag, you do not need to add the `argNames` attribute, since the compiler retains the
|
||||
needed information.
|
||||
====
|
||||
|
||||
The following example shows how to use the `argNames` attribute:
|
||||
|
||||
* If the parameter names have been explicitly specified by the user, the specified
|
||||
parameter names are used. Both the advice and the pointcut annotations have
|
||||
an optional `argNames` attribute that you can use to specify the argument names of
|
||||
the annotated method. These argument names are available at runtime. The following example
|
||||
shows how to use the `argNames` attribute:
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim",role="primary"]
|
||||
.Java
|
||||
----
|
||||
|
@ -1549,7 +1586,7 @@ following strategy to determine parameter names:
|
|||
}
|
||||
----
|
||||
<1> References the `publicMethod` named pointcut defined in <<aop-pointcuts-combining>>.
|
||||
+
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
|
@ -1562,12 +1599,12 @@ following strategy to determine parameter names:
|
|||
}
|
||||
----
|
||||
<1> References the `publicMethod` named pointcut defined in <<aop-pointcuts-combining>>.
|
||||
+
|
||||
If the first parameter is of the `JoinPoint`, `ProceedingJoinPoint`, or
|
||||
`JoinPoint.StaticPart` type, you can leave out the name of the parameter from the value
|
||||
of the `argNames` attribute. For example, if you modify the preceding advice to receive
|
||||
the join point object, the `argNames` attribute need not include it:
|
||||
+
|
||||
|
||||
If the first parameter is of type `JoinPoint`, `ProceedingJoinPoint`, or
|
||||
`JoinPoint.StaticPart`, you can omit the name of the parameter from the value of the
|
||||
`argNames` attribute. For example, if you modify the preceding advice to receive the join
|
||||
point object, the `argNames` attribute does not need to include it:
|
||||
|
||||
[source,java,indent=0,subs="verbatim",role="primary"]
|
||||
.Java
|
||||
----
|
||||
|
@ -1580,7 +1617,7 @@ the join point object, the `argNames` attribute need not include it:
|
|||
}
|
||||
----
|
||||
<1> References the `publicMethod` named pointcut defined in <<aop-pointcuts-combining>>.
|
||||
+
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
|
@ -1593,13 +1630,13 @@ the join point object, the `argNames` attribute need not include it:
|
|||
}
|
||||
----
|
||||
<1> References the `publicMethod` named pointcut defined in <<aop-pointcuts-combining>>.
|
||||
+
|
||||
|
||||
The special treatment given to the first parameter of the `JoinPoint`,
|
||||
`ProceedingJoinPoint`, and `JoinPoint.StaticPart` types is particularly convenient for
|
||||
advice instances that do not collect any other join point context. In such situations, you may
|
||||
omit the `argNames` attribute. For example, the following advice need not declare
|
||||
the `argNames` attribute:
|
||||
+
|
||||
advice instances that do not collect any other join point context. In such situations,
|
||||
you may omit the `argNames` attribute. For example, the following advice does not need to
|
||||
declare the `argNames` attribute:
|
||||
|
||||
[source,java,indent=0,subs="verbatim",role="primary"]
|
||||
.Java
|
||||
----
|
||||
|
@ -1609,7 +1646,7 @@ the `argNames` attribute:
|
|||
}
|
||||
----
|
||||
<1> References the `publicMethod` named pointcut defined in <<aop-pointcuts-combining>>.
|
||||
+
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
|
@ -1620,27 +1657,6 @@ the `argNames` attribute:
|
|||
----
|
||||
<1> References the `publicMethod` named pointcut defined in <<aop-pointcuts-combining>>.
|
||||
|
||||
* Using the `argNames` attribute is a little clumsy, so if the `argNames` attribute
|
||||
has not been specified, Spring AOP looks at the debug information for the
|
||||
class and tries to determine the parameter names from the local variable table. This
|
||||
information is present as long as the classes have been compiled with debug
|
||||
information (`-g:vars` at a minimum). The consequences of compiling with this flag
|
||||
on are: (1) your code is slightly easier to understand (reverse engineer), (2)
|
||||
the class file sizes are very slightly bigger (typically inconsequential), (3) the
|
||||
optimization to remove unused local variables is not applied by your compiler. In
|
||||
other words, you should encounter no difficulties by building with this flag on.
|
||||
+
|
||||
NOTE: If an @AspectJ aspect has been compiled by the AspectJ compiler (`ajc`) even
|
||||
without the debug information, you need not add the `argNames` attribute, as the compiler
|
||||
retains the needed information.
|
||||
|
||||
* If the code has been compiled without the necessary debug information, Spring AOP
|
||||
tries to deduce the pairing of binding variables to parameters (for example, if
|
||||
only one variable is bound in the pointcut expression, and the advice method
|
||||
takes only one parameter, the pairing is obvious). If the binding of variables is
|
||||
ambiguous given the available information, an `AmbiguousBindingException` is
|
||||
thrown.
|
||||
* If all of the above strategies fail, an `IllegalArgumentException` is thrown.
|
||||
|
||||
[[aop-ataspectj-advice-proceeding-with-the-call]]
|
||||
===== Proceeding with Arguments
|
||||
|
|
Loading…
Reference in New Issue