Version 2

    Dynamic AOP

     

    Overview

    JBossAOP has a few features for Dynamic AOP.  What is Dynamic AOP?  It is two things

     

    • Per Instance Interception.  The ability to do more fine grained bindings at the instance level.  So that two instances of the same class can have two separate interceptor/advice chains.

    • Hot Deployment.  The ability to add and remove advice bindings at runtime to any prepared Java class.

     

    Prepare

    In order to use dynamic AOP, classes must first be "prepared".  The preparation phase requires XML that tells the AOPC or AOP SystemClassLoader to do some simple bytecode manipulation on the prepared class so that it can do dynamic aop.  This transformation is the same as any transformation triggered by a regular binding, except that no advince bindings are required.  This added bytecode has low overhead.  Run the Benchmark example to see how high the overhead is.  For this example, open up jboss-aop.xml to see how the files are prepared

     

       <prepare expr="all(POJO)"></prepare>
    

    This expression simple states to prepare all constructor, method, and field access to be AOPable.  Actually, any expression will cause a Java class to be "prepared".

     

    Per Instance Interception

    Let's look at the first type of Dynamic AOP.  You can add interceptors on a per instance basis using the org.jboss.aop.InstanceAdvisor API.  (see the javadocs).  All "prepared" java classes implement org.jboss.aop.Advised.  Advised has a method _getInstanceAdvisor that gives you access to the InstanceAdvisor api.  Added interceptors are put before and after the main ClassAdvisor interceptor chain.  InstanceAdvisor.insertInterceptor puts an interceptor at the beginning of the advice/interceptor chain.  InstanceAdvisor.appendInterceptor puts it at the end.  Another quirkiness about this api is that the interceptors will be added to every chain of every method, field, or constructor so the added interceptor must do a runtime check to determine if it should execute or not.  In the future we plan to have more fine-grained control over this, but we didn't get to it in the 1.0Beta release, sorry!

     

    You can see this in action within Driver.java

          System.out.println("--- adding instance interceptors ---");
          Advised advised = (Advised)pojo;
          advised._getInstanceAdvisor().insertInterceptor(new InstanceInterceptor());
    

     

    Driver.java typecasts the pojo instance to Advised.  From the Advised interface, the code gets access to the InstanceAdvisor API and inserts an interceptor.

     

    Hot Deployment

    Another thing to notice in the Driver.java source file is that the code is creating an AdviceBinding at runtime and applying it to the POJO class.

     

          AdviceBinding binding = new AdviceBinding("execution(POJO->new(..))", null);
          binding.addInterceptor(SimpleInterceptor.class);
          AspectManager.instance().addBinding(binding);
    

     

    You can also remove bindings at runtime as well through the AspectManager class.  See javadocs for more detail.

     

    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] in empty constructor
         [java] --- adding instance interceptors ---
         [java] --- pojo.counter++; ---
         [java] <<< Entering Instancenterceptor for: org.jboss.aop.joinpoint.FieldReadInvocation
         [java] <<< Entering Instancenterceptor for: org.jboss.aop.joinpoint.FieldWriteInvocation
         [java] --- pojo.someMethod(); ---
         [java] <<< Entering Instancenterceptor for: org.jboss.aop.joinpoint.MethodInvocation
         [java] in someMethod
         [java] --- new POJO(); ---
         [java] <<< Entering Simplenterceptor for: org.jboss.aop.joinpoint.ConstructorInvocation
         [java] in empty constructor
         [java] --- adding instance interceptors ---
         [java] --- pojo.counter++; ---
         [java] <<< Entering Instancenterceptor for: org.jboss.aop.joinpoint.FieldReadInvocation
         [java] <<< Entering Instancenterceptor for: org.jboss.aop.joinpoint.FieldWriteInvocation
         [java] --- pojo.someMethod(); ---
         [java] <<< Entering Instancenterceptor for: org.jboss.aop.joinpoint.MethodInvocation
         [java] in someMethod