JBoss.org Community Documentation
As we saw, an advice can receive the joinpoint arguments as annotated parameters. This can be achieved with the use of
two different annotations: @Arg
and @Args
.
There is a great difference between these two approaches, though. With @Arg
, each parameter is equivalent
to a single joinpoint parameter. With @Args
, one single parameter, of type Object[]
,
receives an array containing all joinpoint arguments. This last possibility is more generic than the first one, since it can be
used independently of the joinpoint argument types. Plus, it allows changes to the argument values. Any changes performed on
the values of this array will be perpetuated to the joinpoint execution. However, the use of @Args
parameters
on a join point interception means the arguments array needs creation. The same happens with the use of
getArguments()
and setArguments()
methods on Invocation
classes. So the
use of @Arg
annotated parameters is more lightweight, and should be used whenever there is no need to changing
the joinpoint arguments.
When using @Arg
annotated parameters, the types of these parameters depend on the joinpoint being intercepted.
Not all the target joinpoint arguments need to be included as parameters to the advice method. An advice can receive only the
argument values that are relevant to its execution.
Given all the possibilities in the usage of @Arg
, JBoss AOP will match the advice parameters with the
joinpoint ones, to infer to which joinpoint argument each advice parameter refers to. This matching process consists of
the following steps:
Each advice parameter will be matched to the first unmatched joinpoint argument that has the same type. This is done in the order that the advice parameters appear in the advice method.
If any advice parameter is left unmatched, we proceed to an additional step. Each advice parameter will be matched to the first unmatched joinpoint argument that is assignable to it. This is done in the order that the advice parameters appear in the advice method declaration.
To illustrate this mechanism, consider the following scenario:
public class POJO { void method(Collection arg0, List arg1, int arg2, String arg3){} } <aop> <aspect class="MyAspect"/> <bind pointcut="execution(* POJO->method(..))"> <before aspect="MyAspect" name="advice"/> </bind> </aop>
The example above shows a xml-declared binding. We will use examples with those to illustrate signature concepts from now on. Detailed syntax of xml bindings is shown in Chapter 5, XML Bindings .
Class POJO
is a plain java old object that contains only one method.
When calling this method, we want to trigger MyAspet.advice()
before this
method is called. POJO.method()
receives four distinct arguments, all of them
can be available to an advice by using @Arg
annotated parameters. If
MyAspect.advice()
has the following signature:
public class MyAspect { public void advice(@Arg Collection param0, @Arg List param1, @Arg int param2, @Arg String param3) { ... } }
MyAspect.advice()
parameters will be trivially matched to POJO.method()
arguments
as follows:
param0 <- arg0 param1 <- arg1 param2 <- arg2 param3 <- arg3
The matching outcome will be the same if MyAspect.advice()
signature changes slightly in the following
manner, since Collection
is assignable from List
for param2
:
public class MyAspect { public void advice (@Arg Collection param0, @Arg Collection param1, @Arg int param2, @Arg String param3) { ... } }
If MyAspect.advice()
receives only one parameter, of type java.lang.Object
:
public class MyAspect { public void advice(@Arg Object param0) { ... } }
The parameter matching outcome will be:
param0 <- arg0
Since there is no joinpoint argument of type Object
, we proceed to the additional
matching step in this case. Because arg0
is the first unmatched argument that is assignable
to Object
, we assign this argument to param0
.
Notice that JBoss AOP will match all parameters correctly if we invert the order of parameters:
public class MyAspect { public void advice(@Arg int param2, @Arg Collection param0, @Arg String param3, @Arg List param1) { ... } }
If one writes an advice whose unique parameter is a Collection
, and we want to refer
to the second joinpoint argument:
public class MyAspect { public void advice (@Arg Collection param1) { ... } }
It will not work as desired. JBoss AOP will assign arg0
to param1
:
param1 <- arg0
In cases like this, it is possible to enforce the correct matching of joinpoint arguments and
advice parameters. The annotation @Arg
has an attribute, index, whose purpose
is to define the index of the argument to which that parameter refers.
So, in this case, the MyAspect.advice()
parameter list below:
public class MyAspect { public void advice (@Arg(index=1) Collection param1) { ... } }
Will have the desired matching, which is:
param1 <- arg1
In the example just shown in this section, MyAspect.advice()
was a before advice,
but the same rules are used for all advices using @Arg
annotated parameters.