JBoss.org Community Documentation

4.3.2. JoinPoint Arguments

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.