|
|
|
@ -925,7 +925,6 @@ You can declare before advice in an aspect by using the `@Before` annotation: |
|
|
|
public void doAccessCheck() { |
|
|
|
public void doAccessCheck() { |
|
|
|
// ... |
|
|
|
// ... |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
@ -941,7 +940,6 @@ You can declare before advice in an aspect by using the `@Before` annotation: |
|
|
|
fun doAccessCheck() { |
|
|
|
fun doAccessCheck() { |
|
|
|
// ... |
|
|
|
// ... |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
@ -961,7 +959,6 @@ following example: |
|
|
|
public void doAccessCheck() { |
|
|
|
public void doAccessCheck() { |
|
|
|
// ... |
|
|
|
// ... |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
[source,kotlin,indent=0,subs="verbatim",role="secondary"] |
|
|
|
[source,kotlin,indent=0,subs="verbatim",role="secondary"] |
|
|
|
@ -977,7 +974,6 @@ following example: |
|
|
|
fun doAccessCheck() { |
|
|
|
fun doAccessCheck() { |
|
|
|
// ... |
|
|
|
// ... |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
@ -985,8 +981,8 @@ following example: |
|
|
|
[[aop-advice-after-returning]] |
|
|
|
[[aop-advice-after-returning]] |
|
|
|
==== After Returning Advice |
|
|
|
==== After Returning Advice |
|
|
|
|
|
|
|
|
|
|
|
After returning advice runs when a matched method execution returns normally. You can |
|
|
|
After returning advice runs when a matched method execution returns normally. |
|
|
|
declare it by using the `@AfterReturning` annotation: |
|
|
|
You can declare it by using the `@AfterReturning` annotation: |
|
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
.Java |
|
|
|
.Java |
|
|
|
@ -1001,7 +997,6 @@ declare it by using the `@AfterReturning` annotation: |
|
|
|
public void doAccessCheck() { |
|
|
|
public void doAccessCheck() { |
|
|
|
// ... |
|
|
|
// ... |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
@ -1017,16 +1012,16 @@ declare it by using the `@AfterReturning` annotation: |
|
|
|
fun doAccessCheck() { |
|
|
|
fun doAccessCheck() { |
|
|
|
// ... |
|
|
|
// ... |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
NOTE: You can have multiple advice declarations (and other members |
|
|
|
NOTE: You can have multiple advice declarations (and other members as well), |
|
|
|
as well), all inside the same aspect. We show only a single advice declaration in |
|
|
|
all inside the same aspect. We show only a single advice declaration in these |
|
|
|
these examples to focus the effect of each one. |
|
|
|
examples to focus the effect of each one. |
|
|
|
|
|
|
|
|
|
|
|
Sometimes, you need access in the advice body to the actual value that was returned. You |
|
|
|
Sometimes, you need access in the advice body to the actual value that was returned. |
|
|
|
can use the form of `@AfterReturning` that binds the return value to get that access, as |
|
|
|
You can use the form of `@AfterReturning` that binds the return value to get that |
|
|
|
the following example shows: |
|
|
|
access, as the following example shows: |
|
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
.Java |
|
|
|
.Java |
|
|
|
@ -1043,7 +1038,6 @@ the following example shows: |
|
|
|
public void doAccessCheck(Object retVal) { |
|
|
|
public void doAccessCheck(Object retVal) { |
|
|
|
// ... |
|
|
|
// ... |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
@ -1061,15 +1055,14 @@ the following example shows: |
|
|
|
fun doAccessCheck(retVal: Any) { |
|
|
|
fun doAccessCheck(retVal: Any) { |
|
|
|
// ... |
|
|
|
// ... |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
The name used in the `returning` attribute must correspond to the name of a parameter in |
|
|
|
The name used in the `returning` attribute must correspond to the name of a parameter |
|
|
|
the advice method. When a method execution returns, the return value is passed to |
|
|
|
in the advice method. When a method execution returns, the return value is passed to |
|
|
|
the advice method as the corresponding argument value. A `returning` clause also |
|
|
|
the advice method as the corresponding argument value. A `returning` clause also |
|
|
|
restricts matching to only those method executions that return a value of the specified |
|
|
|
restricts matching to only those method executions that return a value of the |
|
|
|
type (in this case, `Object`, which matches any return value). |
|
|
|
specified type (in this case, `Object`, which matches any return value). |
|
|
|
|
|
|
|
|
|
|
|
Please note that it is not possible to return a totally different reference when |
|
|
|
Please note that it is not possible to return a totally different reference when |
|
|
|
using after returning advice. |
|
|
|
using after returning advice. |
|
|
|
@ -1079,8 +1072,8 @@ using after returning advice. |
|
|
|
==== After Throwing Advice |
|
|
|
==== After Throwing Advice |
|
|
|
|
|
|
|
|
|
|
|
After throwing advice runs when a matched method execution exits by throwing an |
|
|
|
After throwing advice runs when a matched method execution exits by throwing an |
|
|
|
exception. You can declare it by using the `@AfterThrowing` annotation, as the following |
|
|
|
exception. You can declare it by using the `@AfterThrowing` annotation, as the |
|
|
|
example shows: |
|
|
|
following example shows: |
|
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
.Java |
|
|
|
.Java |
|
|
|
@ -1095,7 +1088,6 @@ example shows: |
|
|
|
public void doRecoveryActions() { |
|
|
|
public void doRecoveryActions() { |
|
|
|
// ... |
|
|
|
// ... |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
@ -1111,15 +1103,14 @@ example shows: |
|
|
|
fun doRecoveryActions() { |
|
|
|
fun doRecoveryActions() { |
|
|
|
// ... |
|
|
|
// ... |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
Often, you want the advice to run only when exceptions of a given type are thrown, and |
|
|
|
Often, you want the advice to run only when exceptions of a given type are thrown, |
|
|
|
you also often need access to the thrown exception in the advice body. You can use the |
|
|
|
and you also often need access to the thrown exception in the advice body. You can |
|
|
|
`throwing` attribute to both restrict matching (if desired -- use `Throwable` as the |
|
|
|
use the `throwing` attribute to both restrict matching (if desired -- use `Throwable` |
|
|
|
exception type otherwise) and bind the thrown exception to an advice parameter. The |
|
|
|
as the exception type otherwise) and bind the thrown exception to an advice parameter. |
|
|
|
following example shows how to do so: |
|
|
|
The following example shows how to do so: |
|
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
.Java |
|
|
|
.Java |
|
|
|
@ -1136,7 +1127,6 @@ following example shows how to do so: |
|
|
|
public void doRecoveryActions(DataAccessException ex) { |
|
|
|
public void doRecoveryActions(DataAccessException ex) { |
|
|
|
// ... |
|
|
|
// ... |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
@ -1154,15 +1144,22 @@ following example shows how to do so: |
|
|
|
fun doRecoveryActions(ex: DataAccessException) { |
|
|
|
fun doRecoveryActions(ex: DataAccessException) { |
|
|
|
// ... |
|
|
|
// ... |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
The name used in the `throwing` attribute must correspond to the name of a parameter in |
|
|
|
The name used in the `throwing` attribute must correspond to the name of a parameter in |
|
|
|
the advice method. When a method execution exits by throwing an exception, the exception |
|
|
|
the advice method. When a method execution exits by throwing an exception, the exception |
|
|
|
is passed to the advice method as the corresponding argument value. A `throwing` |
|
|
|
is passed to the advice method as the corresponding argument value. A `throwing` clause |
|
|
|
clause also restricts matching to only those method executions that throw an exception |
|
|
|
also restricts matching to only those method executions that throw an exception of the |
|
|
|
of the specified type ( `DataAccessException`, in this case). |
|
|
|
specified type (`DataAccessException`, in this case). |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[NOTE] |
|
|
|
|
|
|
|
==== |
|
|
|
|
|
|
|
Note that `@AfterThrowing` does not indicate a general exception handling callback. |
|
|
|
|
|
|
|
Specifically, an `@AfterThrowing` advice method is only supposed to receive exceptions |
|
|
|
|
|
|
|
from the join point (user-declared target method) itself but not from an accompanying |
|
|
|
|
|
|
|
`@After`/`@AfterReturning` method. |
|
|
|
|
|
|
|
==== |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[aop-advice-after-finally]] |
|
|
|
[[aop-advice-after-finally]] |
|
|
|
@ -1170,8 +1167,8 @@ of the specified type ( `DataAccessException`, in this case). |
|
|
|
|
|
|
|
|
|
|
|
After (finally) advice runs when a matched method execution exits. It is declared by |
|
|
|
After (finally) advice runs when a matched method execution exits. It is declared by |
|
|
|
using the `@After` annotation. After advice must be prepared to handle both normal and |
|
|
|
using the `@After` annotation. After advice must be prepared to handle both normal and |
|
|
|
exception return conditions. It is typically used for releasing resources and similar purposes. |
|
|
|
exception return conditions. It is typically used for releasing resources and similar |
|
|
|
The following example shows how to use after finally advice: |
|
|
|
purposes. The following example shows how to use after finally advice: |
|
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
.Java |
|
|
|
.Java |
|
|
|
@ -1186,7 +1183,6 @@ The following example shows how to use after finally advice: |
|
|
|
public void doReleaseLock() { |
|
|
|
public void doReleaseLock() { |
|
|
|
// ... |
|
|
|
// ... |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
@ -1202,30 +1198,37 @@ The following example shows how to use after finally advice: |
|
|
|
fun doReleaseLock() { |
|
|
|
fun doReleaseLock() { |
|
|
|
// ... |
|
|
|
// ... |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[NOTE] |
|
|
|
|
|
|
|
==== |
|
|
|
|
|
|
|
Note that `@After` advice in AspectJ is defined as "after finally advice", analogous |
|
|
|
|
|
|
|
to a finally block in a try-catch statement. It will be invoked for any outcome, |
|
|
|
|
|
|
|
normal return or exception thrown from the join point (user-declared target method), |
|
|
|
|
|
|
|
in contrast to `@AfterReturning` which only applies to successful normal returns. |
|
|
|
|
|
|
|
==== |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[aop-ataspectj-around-advice]] |
|
|
|
[[aop-ataspectj-around-advice]] |
|
|
|
==== Around Advice |
|
|
|
==== Around Advice |
|
|
|
|
|
|
|
|
|
|
|
The last kind of advice is around advice. Around advice runs "`around`" a matched method's |
|
|
|
The last kind of advice is around advice. Around advice runs "`around`" a matched |
|
|
|
execution. It has the opportunity to do work both before and after the method runs |
|
|
|
method's execution. It has the opportunity to do work both before and after the method |
|
|
|
and to determine when, how, and even if the method actually gets to run at all. |
|
|
|
runs and to determine when, how, and even if the method actually gets to run at all. |
|
|
|
Around advice is often used if you need to share state before and after a method |
|
|
|
Around advice is often used if you need to share state before and after a method |
|
|
|
execution in a thread-safe manner (starting and stopping a timer, for example). Always |
|
|
|
execution in a thread-safe manner (starting and stopping a timer, for example). |
|
|
|
use the least powerful form of advice that meets your requirements (that is, do not use |
|
|
|
Always use the least powerful form of advice that meets your requirements (that is, |
|
|
|
around advice if before advice would do). |
|
|
|
do not use around advice if before advice would do). |
|
|
|
|
|
|
|
|
|
|
|
Around advice is declared by using the `@Around` annotation. The first parameter of the |
|
|
|
Around advice is declared by using the `@Around` annotation. The first parameter of the |
|
|
|
advice method must be of type `ProceedingJoinPoint`. Within the body of the advice, |
|
|
|
advice method must be of type `ProceedingJoinPoint`. Within the body of the advice, |
|
|
|
calling `proceed()` on the `ProceedingJoinPoint` causes the underlying method to |
|
|
|
calling `proceed()` on the `ProceedingJoinPoint` causes the underlying method to run. |
|
|
|
run. The `proceed` method can also pass in an `Object[]`. The values |
|
|
|
The `proceed` method can also pass in an `Object[]`. The values in the array are used |
|
|
|
in the array are used as the arguments to the method execution when it proceeds. |
|
|
|
as the arguments to the method execution when it proceeds. |
|
|
|
|
|
|
|
|
|
|
|
NOTE: The behavior of `proceed` when called with an `Object[]` is a little different than the |
|
|
|
NOTE: The behavior of `proceed` when called with an `Object[]` is a little different than |
|
|
|
behavior of `proceed` for around advice compiled by the AspectJ compiler. For around |
|
|
|
the behavior of `proceed` for around advice compiled by the AspectJ compiler. For around |
|
|
|
advice written using the traditional AspectJ language, the number of arguments passed to |
|
|
|
advice written using the traditional AspectJ language, the number of arguments passed to |
|
|
|
`proceed` must match the number of arguments passed to the around advice (not the number |
|
|
|
`proceed` must match the number of arguments passed to the around advice (not the number |
|
|
|
of arguments taken by the underlying join point), and the value passed to proceed in a |
|
|
|
of arguments taken by the underlying join point), and the value passed to proceed in a |
|
|
|
@ -1257,7 +1260,6 @@ The following example shows how to use around advice: |
|
|
|
// stop stopwatch |
|
|
|
// stop stopwatch |
|
|
|
return retVal; |
|
|
|
return retVal; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
@ -1277,34 +1279,31 @@ The following example shows how to use around advice: |
|
|
|
// stop stopwatch |
|
|
|
// stop stopwatch |
|
|
|
return retVal |
|
|
|
return retVal |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
The value returned by the around advice is the return value seen by the caller of |
|
|
|
The value returned by the around advice is the return value seen by the caller of the |
|
|
|
the method. For example, a simple caching aspect could return a value from a cache if it |
|
|
|
method. For example, a simple caching aspect could return a value from a cache if it |
|
|
|
has one and invoke `proceed()` if it does not. Note that `proceed` may be invoked once, |
|
|
|
has one and invoke `proceed()` if it does not. Note that `proceed` may be invoked once, |
|
|
|
many times, or not at all within the body of the around advice. All of these are |
|
|
|
many times, or not at all within the body of the around advice. All of these are legal. |
|
|
|
legal. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[aop-ataspectj-advice-params]] |
|
|
|
[[aop-ataspectj-advice-params]] |
|
|
|
==== Advice Parameters |
|
|
|
==== Advice Parameters |
|
|
|
|
|
|
|
|
|
|
|
Spring offers fully typed advice, meaning that you declare the parameters you need |
|
|
|
Spring offers fully typed advice, meaning that you declare the parameters you need in the |
|
|
|
in the advice signature (as we saw earlier for the returning and throwing examples) rather |
|
|
|
advice signature (as we saw earlier for the returning and throwing examples) rather than |
|
|
|
than work with `Object[]` arrays all the time. We see how to make argument and other |
|
|
|
work with `Object[]` arrays all the time. We see how to make argument and other contextual |
|
|
|
contextual values available to the advice body later in this section. First, we take a look at |
|
|
|
values available to the advice body later in this section. First, we take a look at how to |
|
|
|
how to write generic advice that can find out about the method the advice is currently |
|
|
|
write generic advice that can find out about the method the advice is currently advising. |
|
|
|
advising. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[aop-ataspectj-advice-params-the-joinpoint]] |
|
|
|
[[aop-ataspectj-advice-params-the-joinpoint]] |
|
|
|
===== Access to the Current `JoinPoint` |
|
|
|
===== Access to the Current `JoinPoint` |
|
|
|
|
|
|
|
|
|
|
|
Any advice method may declare, as its first parameter, a parameter of type |
|
|
|
Any advice method may declare, as its first parameter, a parameter of type |
|
|
|
`org.aspectj.lang.JoinPoint` (note that around advice is required to declare |
|
|
|
`org.aspectj.lang.JoinPoint` (note that around advice is required to declare a first |
|
|
|
a first parameter of type `ProceedingJoinPoint`, which is a subclass of `JoinPoint`. The |
|
|
|
parameter of type `ProceedingJoinPoint`, which is a subclass of `JoinPoint`. |
|
|
|
`JoinPoint` interface provides a number of useful methods: |
|
|
|
The `JoinPoint` interface provides a number of useful methods: |
|
|
|
|
|
|
|
|
|
|
|
* `getArgs()`: Returns the method arguments. |
|
|
|
* `getArgs()`: Returns the method arguments. |
|
|
|
* `getThis()`: Returns the proxy object. |
|
|
|
* `getThis()`: Returns the proxy object. |
|
|
|
@ -1320,9 +1319,9 @@ See the https://www.eclipse.org/aspectj/doc/released/runtime-api/org/aspectj/lan |
|
|
|
We have already seen how to bind the returned value or exception value (using after |
|
|
|
We have already seen how to bind the returned value or exception value (using after |
|
|
|
returning and after throwing advice). To make argument values available to the advice |
|
|
|
returning and after throwing advice). To make argument values available to the advice |
|
|
|
body, you can use the binding form of `args`. If you use a parameter name in place of a |
|
|
|
body, you can use the binding form of `args`. If you use a parameter name in place of a |
|
|
|
type name in an args expression, the value of the corresponding argument is |
|
|
|
type name in an args expression, the value of the corresponding argument is passed as |
|
|
|
passed as the parameter value when the advice is invoked. An example should make this |
|
|
|
the parameter value when the advice is invoked. An example should make this clearer. |
|
|
|
clearer. Suppose you want to advise the execution of DAO operations that take an `Account` |
|
|
|
Suppose you want to advise the execution of DAO operations that take an `Account` |
|
|
|
object as the first parameter, and you need access to the account in the advice body. |
|
|
|
object as the first parameter, and you need access to the account in the advice body. |
|
|
|
You could write the following: |
|
|
|
You could write the following: |
|
|
|
|
|
|
|
|
|
|
|
@ -1654,20 +1653,23 @@ the higher precedence. |
|
|
|
|
|
|
|
|
|
|
|
[NOTE] |
|
|
|
[NOTE] |
|
|
|
==== |
|
|
|
==== |
|
|
|
|
|
|
|
Each of the distinct advice types of a particular aspect is conceptually meant to apply |
|
|
|
|
|
|
|
to the join point directly. As a consequence, an `@AfterThrowing` advice method is not |
|
|
|
|
|
|
|
supposed to receive an exception from an accompanying `@After`/`@AfterReturning` method. |
|
|
|
|
|
|
|
|
|
|
|
As of Spring Framework 5.2.7, advice methods defined in the same `@Aspect` class that |
|
|
|
As of Spring Framework 5.2.7, advice methods defined in the same `@Aspect` class that |
|
|
|
need to run at the same join point are assigned precedence based on their advice type in |
|
|
|
need to run at the same join point are assigned precedence based on their advice type in |
|
|
|
the following order, from highest to lowest precedence: `@Around`, `@Before`, `@After`, |
|
|
|
the following order, from highest to lowest precedence: `@Around`, `@Before`, `@After`, |
|
|
|
`@AfterReturning`, `@AfterThrowing`. Note, however, that due to the implementation style |
|
|
|
`@AfterReturning`, `@AfterThrowing`. Note, however, that an `@After` advice method will |
|
|
|
in Spring's `AspectJAfterAdvice`, an `@After` advice method will effectively be invoked |
|
|
|
effectively be invoked after any `@AfterReturning` or `@AfterThrowing` advice methods |
|
|
|
after any `@AfterReturning` or `@AfterThrowing` advice methods in the same aspect. |
|
|
|
in the same aspect, following AspectJ's "after finally advice" semantics for `@After`. |
|
|
|
|
|
|
|
|
|
|
|
When two pieces of the same type of advice (for example, two `@After` advice methods) |
|
|
|
When two pieces of the same type of advice (for example, two `@After` advice methods) |
|
|
|
defined in the same `@Aspect` class both need to run at the same join point, the ordering |
|
|
|
defined in the same `@Aspect` class both need to run at the same join point, the ordering |
|
|
|
is undefined (since there is no way to retrieve the source code declaration order through |
|
|
|
is undefined (since there is no way to retrieve the source code declaration order through |
|
|
|
reflection for javac-compiled classes). Consider collapsing such advice methods into one |
|
|
|
reflection for javac-compiled classes). Consider collapsing such advice methods into one |
|
|
|
advice method per join point in each `@Aspect` class or refactor the pieces of advice |
|
|
|
advice method per join point in each `@Aspect` class or refactor the pieces of advice into |
|
|
|
into separate `@Aspect` classes that you can order at the aspect level via `Ordered` or |
|
|
|
separate `@Aspect` classes that you can order at the aspect level via `Ordered` or `@Order`. |
|
|
|
`@Order`. |
|
|
|
|
|
|
|
==== |
|
|
|
==== |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1678,11 +1680,11 @@ Introductions (known as inter-type declarations in AspectJ) enable an aspect to |
|
|
|
that advised objects implement a given interface, and to provide an implementation of |
|
|
|
that advised objects implement a given interface, and to provide an implementation of |
|
|
|
that interface on behalf of those objects. |
|
|
|
that interface on behalf of those objects. |
|
|
|
|
|
|
|
|
|
|
|
You can make an introduction by using the `@DeclareParents` annotation. This annotation is used |
|
|
|
You can make an introduction by using the `@DeclareParents` annotation. This annotation |
|
|
|
to declare that matching types have a new parent (hence the name). For example, given an |
|
|
|
is used to declare that matching types have a new parent (hence the name). For example, |
|
|
|
interface named `UsageTracked` and an implementation of that interface named `DefaultUsageTracked`, |
|
|
|
given an interface named `UsageTracked` and an implementation of that interface named |
|
|
|
the following aspect declares that all implementors of service interfaces also implement |
|
|
|
`DefaultUsageTracked`, the following aspect declares that all implementors of service |
|
|
|
the `UsageTracked` interface (to expose statistics via JMX for example): |
|
|
|
interfaces also implement the `UsageTracked` interface (e.g. for statistics via JMX): |
|
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
.Java |
|
|
|
.Java |
|
|
|
@ -1764,7 +1766,6 @@ annotation. Consider the following example: |
|
|
|
public void recordServiceUsage() { |
|
|
|
public void recordServiceUsage() { |
|
|
|
// ... |
|
|
|
// ... |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
@ -1779,7 +1780,6 @@ annotation. Consider the following example: |
|
|
|
fun recordServiceUsage() { |
|
|
|
fun recordServiceUsage() { |
|
|
|
// ... |
|
|
|
// ... |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
@ -1854,7 +1854,6 @@ call `proceed` multiple times. The following listing shows the basic aspect impl |
|
|
|
} while(numAttempts <= this.maxRetries); |
|
|
|
} while(numAttempts <= this.maxRetries); |
|
|
|
throw lockFailureException; |
|
|
|
throw lockFailureException; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
@ -2066,7 +2065,6 @@ as the following example shows: |
|
|
|
expression="execution(* com.xyz.myapp.service.*.*(..))"/> |
|
|
|
expression="execution(* com.xyz.myapp.service.*.*(..))"/> |
|
|
|
|
|
|
|
|
|
|
|
... |
|
|
|
... |
|
|
|
|
|
|
|
|
|
|
|
</aop:aspect> |
|
|
|
</aop:aspect> |
|
|
|
|
|
|
|
|
|
|
|
</aop:config> |
|
|
|
</aop:config> |
|
|
|
@ -2088,7 +2086,6 @@ collects the `this` object as the join point context and passes it to the advice |
|
|
|
<aop:before pointcut-ref="businessService" method="monitor"/> |
|
|
|
<aop:before pointcut-ref="businessService" method="monitor"/> |
|
|
|
|
|
|
|
|
|
|
|
... |
|
|
|
... |
|
|
|
|
|
|
|
|
|
|
|
</aop:aspect> |
|
|
|
</aop:aspect> |
|
|
|
|
|
|
|
|
|
|
|
</aop:config> |
|
|
|
</aop:config> |
|
|
|
@ -2179,7 +2176,6 @@ a `pointcut` attribute, as follows: |
|
|
|
method="doAccessCheck"/> |
|
|
|
method="doAccessCheck"/> |
|
|
|
|
|
|
|
|
|
|
|
... |
|
|
|
... |
|
|
|
|
|
|
|
|
|
|
|
</aop:aspect> |
|
|
|
</aop:aspect> |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
@ -2209,7 +2205,6 @@ shows how to declare it: |
|
|
|
method="doAccessCheck"/> |
|
|
|
method="doAccessCheck"/> |
|
|
|
|
|
|
|
|
|
|
|
... |
|
|
|
... |
|
|
|
|
|
|
|
|
|
|
|
</aop:aspect> |
|
|
|
</aop:aspect> |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
@ -2227,7 +2222,6 @@ the return value should be passed, as the following example shows: |
|
|
|
method="doAccessCheck"/> |
|
|
|
method="doAccessCheck"/> |
|
|
|
|
|
|
|
|
|
|
|
... |
|
|
|
... |
|
|
|
|
|
|
|
|
|
|
|
</aop:aspect> |
|
|
|
</aop:aspect> |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
@ -2263,7 +2257,6 @@ as the following example shows: |
|
|
|
method="doRecoveryActions"/> |
|
|
|
method="doRecoveryActions"/> |
|
|
|
|
|
|
|
|
|
|
|
... |
|
|
|
... |
|
|
|
|
|
|
|
|
|
|
|
</aop:aspect> |
|
|
|
</aop:aspect> |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
@ -2281,13 +2274,12 @@ which the exception should be passed as the following example shows: |
|
|
|
method="doRecoveryActions"/> |
|
|
|
method="doRecoveryActions"/> |
|
|
|
|
|
|
|
|
|
|
|
... |
|
|
|
... |
|
|
|
|
|
|
|
|
|
|
|
</aop:aspect> |
|
|
|
</aop:aspect> |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
The `doRecoveryActions` method must declare a parameter named `dataAccessEx`. The type of |
|
|
|
The `doRecoveryActions` method must declare a parameter named `dataAccessEx`. |
|
|
|
this parameter constrains matching in the same way as described for `@AfterThrowing`. For |
|
|
|
The type of this parameter constrains matching in the same way as described for |
|
|
|
example, the method signature may be declared as follows: |
|
|
|
`@AfterThrowing`. For example, the method signature may be declared as follows: |
|
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
|
|
.Java |
|
|
|
.Java |
|
|
|
@ -2304,8 +2296,8 @@ example, the method signature may be declared as follows: |
|
|
|
[[aop-schema-advice-after-finally]] |
|
|
|
[[aop-schema-advice-after-finally]] |
|
|
|
==== After (Finally) Advice |
|
|
|
==== After (Finally) Advice |
|
|
|
|
|
|
|
|
|
|
|
After (finally) advice runs no matter how a matched method execution exits. You can declare it |
|
|
|
After (finally) advice runs no matter how a matched method execution exits. |
|
|
|
by using the `after` element, as the following example shows: |
|
|
|
You can declare it by using the `after` element, as the following example shows: |
|
|
|
|
|
|
|
|
|
|
|
[source,xml,indent=0,subs="verbatim,quotes"] |
|
|
|
[source,xml,indent=0,subs="verbatim,quotes"] |
|
|
|
---- |
|
|
|
---- |
|
|
|
@ -2316,7 +2308,6 @@ by using the `after` element, as the following example shows: |
|
|
|
method="doReleaseLock"/> |
|
|
|
method="doReleaseLock"/> |
|
|
|
|
|
|
|
|
|
|
|
... |
|
|
|
... |
|
|
|
|
|
|
|
|
|
|
|
</aop:aspect> |
|
|
|
</aop:aspect> |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
@ -2327,17 +2318,17 @@ by using the `after` element, as the following example shows: |
|
|
|
The last kind of advice is around advice. Around advice runs "around" a matched method |
|
|
|
The last kind of advice is around advice. Around advice runs "around" a matched method |
|
|
|
execution. It has the opportunity to do work both before and after the method runs |
|
|
|
execution. It has the opportunity to do work both before and after the method runs |
|
|
|
and to determine when, how, and even if the method actually gets to run at all. |
|
|
|
and to determine when, how, and even if the method actually gets to run at all. |
|
|
|
Around advice is often used to share state before and after a method |
|
|
|
Around advice is often used to share state before and after a method execution in a |
|
|
|
execution in a thread-safe manner (starting and stopping a timer, for example). Always |
|
|
|
thread-safe manner (starting and stopping a timer, for example). Always use the least |
|
|
|
use the least powerful form of advice that meets your requirements. Do not use around |
|
|
|
powerful form of advice that meets your requirements. Do not use around advice if |
|
|
|
advice if before advice can do the job. |
|
|
|
before advice can do the job. |
|
|
|
|
|
|
|
|
|
|
|
You can declare around advice by using the `aop:around` element. The first parameter of the |
|
|
|
You can declare around advice by using the `aop:around` element. The first parameter of |
|
|
|
advice method must be of type `ProceedingJoinPoint`. Within the body of the advice, |
|
|
|
the advice method must be of type `ProceedingJoinPoint`. Within the body of the advice, |
|
|
|
calling `proceed()` on the `ProceedingJoinPoint` causes the underlying method to |
|
|
|
calling `proceed()` on the `ProceedingJoinPoint` causes the underlying method to run. |
|
|
|
run. The `proceed` method may also be called with an `Object[]`. The values |
|
|
|
The `proceed` method may also be called with an `Object[]`. The values in the array |
|
|
|
in the array are used as the arguments to the method execution when it proceeds. See |
|
|
|
are used as the arguments to the method execution when it proceeds. |
|
|
|
<<aop-ataspectj-around-advice>> for notes on calling `proceed` with an `Object[]`. |
|
|
|
See <<aop-ataspectj-around-advice>> for notes on calling `proceed` with an `Object[]`. |
|
|
|
The following example shows how to declare around advice in XML: |
|
|
|
The following example shows how to declare around advice in XML: |
|
|
|
|
|
|
|
|
|
|
|
[source,xml,indent=0,subs="verbatim,quotes"] |
|
|
|
[source,xml,indent=0,subs="verbatim,quotes"] |
|
|
|
@ -2349,7 +2340,6 @@ The following example shows how to declare around advice in XML: |
|
|
|
method="doBasicProfiling"/> |
|
|
|
method="doBasicProfiling"/> |
|
|
|
|
|
|
|
|
|
|
|
... |
|
|
|
... |
|
|
|
|
|
|
|
|
|
|
|
</aop:aspect> |
|
|
|
</aop:aspect> |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
@ -2763,7 +2753,6 @@ call `proceed` multiple times. The following listing shows the basic aspect impl |
|
|
|
} while(numAttempts <= this.maxRetries); |
|
|
|
} while(numAttempts <= this.maxRetries); |
|
|
|
throw lockFailureException; |
|
|
|
throw lockFailureException; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
---- |
|
|
|
---- |
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
|
|
|