Interceptor Precedence

Background

In the other examples shown, the ordering of interceptors is according to how they are specified for each binding. This is fine for a lot of cases, but becomes a bit more problematic if you have several bindings resolving to each pointcut. Also, aspects defined using annotations (see reference documentation) have no notion of ordering, how they are ordered is completely random. To examine the case of XML, we have the following two bindings in our jboss-aop.xml file:

   
   <bind pointcut="execution(POJO->new())">
       <interceptor-ref name="FirstInterceptor"/>    
       <interceptor-ref name="SimpleInterceptor3"/>
       <interceptor-ref name="SimpleInterceptor2"/>
       <interceptor-ref name="SimpleInterceptor"/>
   </bind>

   <bind pointcut="execution(PO*->new())">
       <advice aspect="TestAspect" name="otherAdvice"/>
       <advice aspect="TestAspect" name="advice"/>
       <interceptor-ref name="LastInterceptor"/>          
   </bind>   

The default ordering of these would create the following interceptor chain:

   FirstInterceptor
		comes before      
   SimpleInterceptor3
		comes before      
   SimpleInterceptor2
		comes before      
   SimpleInterceptor
		comes before      
   TestAspect.otherAdvice
		comes before      
   TestAspect.advice
		comes before      
   LastInterceptor

Precedence

Now, imagine if the two pointcuts defined were more complex, so that some methods would resolve to the first, some to the second, some to both, and that we would like to be able to merge the interceptor chains according to a predefined order. This is where precedence comes in. It is defined in the jboss-aop.xml file as:

   <precedence>
      <interceptor-ref name="SimpleInterceptor2"/>
      <advice aspect="TestAspect" name="advice"/>
      <interceptor-ref name="SimpleInterceptor3"/>
      <advice aspect="TestAspect" name="otherAdvice"/>
   </precedence>

   <precedence>
      <interceptor-ref name="SimpleInterceptor"/>
      <interceptor-ref name="SimpleInterceptor2"/>
   </precedence>

These two precedence entries each define a relative sorting order of interceptors. You can have as many precedence entries in your jboss-aop.xml file as you like, and as many entries as you would like in each. (Just make sure that the precedence orderings do not conflict.) The precedence entries are merged into an overall precedence entry, so that:

  SimpleInterceptor
		comes before      
  SimpleInterceptor2
		comes before      
  TestAspect.advice
		comes before      
  SimpleInterceptor3
		comes before      
  TestAspect.otherAdvice

If you look at the first jboss-aop.xml snippet containing the bindings you will see that FirstInterceptor and LastInterceptor have not been defined to have a precedence. This means that they will remain where they were before any precedence was applied. Now if you run the example you should see that the advices are sorted and run according to the precedence defined.

Run the example

To compile and run:
  $ ant
It will javac the files and then run the AOPC precompiler to manipulate the bytecode, then finally run the example. The output should read as follows:
run:
     [java] --- new POJO(); ---
     [java] <<< Entering FirstInterceptor type: POJO0OptimizedConstructorInvocation
     [java] <<< Entering SimpleInterceptor type: POJO0OptimizedConstructorInvocation
     [java] <<< Entering SimpleInterceptor2 type: POJO0OptimizedConstructorInvocation
     [java] <<< Entering TestAspect.advice type:POJO0OptimizedConstructorInvocation@6e293a
     [java] <<< Entering SimpleInterceptor3 type: POJO0OptimizedConstructorInvocation
     [java] <<< Entering TestAspect.otherAdvice type:POJO0OptimizedConstructorInvocation@6e293a
     [java] <<< Entering LastInterceptor type: POJO0OptimizedConstructorInvocation
     [java] empty constructor
     [java] >>> Leaving LastInterceptor
     [java] <<< Leaving TestAspect.otherAdvice type:POJO0OptimizedConstructorInvocation@6e293a
     [java] >>> Leaving SimpleInterceptor3
     [java] <<< Leaving TestAspect.advice type:POJO0OptimizedConstructorInvocation@6e293a
     [java] >>> Leaving SimpleInterceptor2
     [java] >>> Leaving SimpleInterceptor
     [java] >>> Leaving FirstInterceptor