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]]
|
[[aop-ataspectj-advice-params-names]]
|
||||||
===== Determining Argument Names
|
===== Determining Argument Names
|
||||||
|
|
||||||
The parameter binding in advice invocations relies on matching names used in pointcut
|
Parameter binding in advice invocations relies on matching the names used in pointcut
|
||||||
expressions to declared parameter names in advice and pointcut method signatures.
|
expressions to the parameter names declared 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:
|
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"]
|
[source,java,indent=0,subs="verbatim",role="primary"]
|
||||||
.Java
|
.Java
|
||||||
----
|
----
|
||||||
|
@ -1549,7 +1586,7 @@ following strategy to determine parameter names:
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
<1> References the `publicMethod` named pointcut defined in <<aop-pointcuts-combining>>.
|
<1> References the `publicMethod` named pointcut defined in <<aop-pointcuts-combining>>.
|
||||||
+
|
|
||||||
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
|
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
|
||||||
.Kotlin
|
.Kotlin
|
||||||
----
|
----
|
||||||
|
@ -1562,12 +1599,12 @@ following strategy to determine parameter names:
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
<1> References the `publicMethod` named pointcut defined in <<aop-pointcuts-combining>>.
|
<1> References the `publicMethod` named pointcut defined in <<aop-pointcuts-combining>>.
|
||||||
+
|
|
||||||
If the first parameter is of the `JoinPoint`, `ProceedingJoinPoint`, or
|
If the first parameter is of type `JoinPoint`, `ProceedingJoinPoint`, or
|
||||||
`JoinPoint.StaticPart` type, you can leave out the name of the parameter from the value
|
`JoinPoint.StaticPart`, you can omit the name of the parameter from the value of the
|
||||||
of the `argNames` attribute. For example, if you modify the preceding advice to receive
|
`argNames` attribute. For example, if you modify the preceding advice to receive the join
|
||||||
the join point object, the `argNames` attribute need not include it:
|
point object, the `argNames` attribute does not need to include it:
|
||||||
+
|
|
||||||
[source,java,indent=0,subs="verbatim",role="primary"]
|
[source,java,indent=0,subs="verbatim",role="primary"]
|
||||||
.Java
|
.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>>.
|
<1> References the `publicMethod` named pointcut defined in <<aop-pointcuts-combining>>.
|
||||||
+
|
|
||||||
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
|
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
|
||||||
.Kotlin
|
.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>>.
|
<1> References the `publicMethod` named pointcut defined in <<aop-pointcuts-combining>>.
|
||||||
+
|
|
||||||
The special treatment given to the first parameter of the `JoinPoint`,
|
The special treatment given to the first parameter of the `JoinPoint`,
|
||||||
`ProceedingJoinPoint`, and `JoinPoint.StaticPart` types is particularly convenient for
|
`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
|
advice instances that do not collect any other join point context. In such situations,
|
||||||
omit the `argNames` attribute. For example, the following advice need not declare
|
you may omit the `argNames` attribute. For example, the following advice does not need to
|
||||||
the `argNames` attribute:
|
declare the `argNames` attribute:
|
||||||
+
|
|
||||||
[source,java,indent=0,subs="verbatim",role="primary"]
|
[source,java,indent=0,subs="verbatim",role="primary"]
|
||||||
.Java
|
.Java
|
||||||
----
|
----
|
||||||
|
@ -1609,7 +1646,7 @@ the `argNames` attribute:
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
<1> References the `publicMethod` named pointcut defined in <<aop-pointcuts-combining>>.
|
<1> References the `publicMethod` named pointcut defined in <<aop-pointcuts-combining>>.
|
||||||
+
|
|
||||||
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
|
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
|
||||||
.Kotlin
|
.Kotlin
|
||||||
----
|
----
|
||||||
|
@ -1620,27 +1657,6 @@ the `argNames` attribute:
|
||||||
----
|
----
|
||||||
<1> References the `publicMethod` named pointcut defined in <<aop-pointcuts-combining>>.
|
<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]]
|
[[aop-ataspectj-advice-proceeding-with-the-call]]
|
||||||
===== Proceeding with Arguments
|
===== Proceeding with Arguments
|
||||||
|
|
Loading…
Reference in New Issue