Version 6

    Reflection

    There are two issues with using the Reflection API with JBoss AOP

     

    1. Aspects applied to constructors and fields are bypassed

    2. JBoss AOP adds a small amount of extra fields and methods

     

    As Java system classes in the java.lang.reflect package cannot be modified by JBoss AOP, the aspect org.jboss.aop.ReflectionAspect has been created to help with these issues. ReflectionAspect contains advices that can be bound with caller pointcuts where needed.

     

    Aspects applied to constructors and fields are bypassed

    The advice org.jboss.aop.ReflectionAspect will intercept your calls if you set up the caller pointcuts properly, but if you want to do something on interception, you can subclass it and override the methods: interceptConstructor(), interceptFieldRead() and interceptFieldWrite().

     

    An example subclass of ReflectionAspect:

         package mypackage;
    
         import java.lang.reflect.Constructor;
         import java.lang.reflect.Field;
    
         import org.jboss.aop.joinpoint.Invocation;
         import org.jboss.aop.reflection.ReflectionAspect;
    
         public class MyReflectionAspect extends ReflectionAspect {
              protected Object interceptConstructor(
              Invocation invocation,
              Constructor constructor,
              Object[] args)
              throws Throwable {
                   //Do your stuff
                   return super.interceptConstructor(invocation, constructor, args);
              }
    
              protected Object interceptFieldRead(
              Invocation invocation,
              Field field,
              Object instance)
              throws Throwable {
                   //Do your stuff
                   return super.interceptFieldRead(invocation, field, instance);
              }
    
              protected Object interceptFieldWrite(
              Invocation invocation,
              Field field,
              Object instance,
              Object arg)
              throws Throwable {
                   //Do your stuff
                   return super.interceptFieldWrite(invocation, field, instance, arg);
              }
         }
    

    As shown below, you will have information about what is being intercepted, so you could do your own filtering on what you do by implementing XmlLoadable in your aspect class.

     

    Declare the aspect example:

      <aspect class="mypackage.MyReflectionAspect" scope="PER_VM"></aspect>
    

     

    Intercepting Class.newInstance()

     

    Bind the interceptNewInstance advice to Class.newInstance() calls:

     

       <bind pointcut="call(* java.lang.Class->newInstance())">
           <advice name="interceptNewInstance" aspect="mypackage.MyReflectionAspect" ></advice>
       </bind>
    

     

    Calls to Class.newInstance() will end up in MyReflectionAspect.interceptConstructor(), and the arguments are:

    invocation - The invocation driving the chain of advices.

    constructor - The constructor being called

    args - the arguments being passed in to the constructor (in this case a zero-length array since Class.newInstance() takes no parameters)

     

     

    Constructor.newInstance()

     

    Bind the interceptNewInstance advice to Constructor.newInstance() calls:

     

       <bind pointcut="call(* java.lang.reflect.Constructor->newInstance())">
           <advice name="interceptNewInstance" aspect="mypackage.MyReflectionAspect" ></advice>
       </bind>
    

     

    Calls to Constructor.newInstance() will end up in MyReflectionAspect.interceptConstructor(), and the arguments are:

    invocation - The invocation driving the chain of advices.

    constructor - The constructor being called

    args - the arguments being passed in to the constructor

     

     

     

    Intercepting Field.getXXX()

     

    Bind the interceptFieldGet advice to Field.get() calls:

     

       <bind pointcut="call(* java.lang.reflect.Field->get*(..))">
              <advice name="interceptFieldGet" aspect="mypackage.MyReflectionAspect" ></advice>
       </bind>
    

     

    Calls to Field->getXXX() will end up in MyReflectionAspect.interceptFieldRead(), and the arguments are:

    invocation - The invocation driving the chain of advices.

    field - The field being read

    instance - the instance on which we are reading a field

     

     

    Intercepting Field.setXXX()

     

    Bind the interceptFieldGet advice to Field.set() calls:

        

       <bind pointcut="call(* java.lang.reflect.Field->set*(..))">
           <advice name="interceptFieldSet" aspect="mypackage.MyReflectionAspect" ></advice>
       </bind>
    

     

    Calls to Field->getXXX() will end up in MyReflectionAspect.interceptFieldWrite(), and the arguments are:

    invocation - The invocation driving the chain of advices.

    field - The field being written

    instance - the instance on which we are writing a field

    arg - the value we are setting the field to

     

     

    Cleaning fields, interfaces and methods added to a class by JBoss AOP

     

    Interfaces

     

    JBoss AOP adds the org.jboss.aop.Advised interface to advised classes. If you intend to be calling Class.getInterfaces() on an advised class, you should bind the interceptGetInterfaces advice to Class.getInterfaces() calls:

     

       <bind pointcut="call(* java.lang.Class->getInterfaces())">
           <advice name="interceptGetInterfaces" aspect="mypackage.MyReflectionAspect" ></advice>
       </bind>
    

     

    Class.getInterfaces() will now return exactly the same as if the class had not been advised (i.e. the original class). This means org.jboss.aop.Advised is not in the list of interfaces returned.

     

    Methods

     

    JBoss AOP adds some methods, both public and private to advised classes.

     

    Bind the interceptGetMethod advice to Class.getMethod() calls:

     

       <bind pointcut="call(* java.lang.Class->getMethod(..))">
           <advice name="interceptGetMethod" aspect="mypackage.MyReflectionAspect" ></advice>
       </bind>
    

     

    Bind the interceptGetDeclaredMethod advice to Class.getMethod() calls:

       <bind pointcut="call(* java.lang.Class->getDeclaredMethod(..))">
           <advice name="interceptGetDeclaredMethod" aspect="mypackage.MyReflectionAspect" ></advice>
       </bind>
    

     

    Both the bindings above intercept the calls so that if you try to get any of the methods in the unadvised class the method is returned as normal. If you try to get one of the methods added by JBoss AOP, a NoSuchMethodException is thrown.

     

    The following advices remove the methods added by JBoss AOP and return the same methods as if the class was unadvised.

     

    Bind the interceptGetDeclaredMethods advice to Class.getDeclaredMethods() calls:

       <bind pointcut="call(* java.lang.Class->getDeclaredMethods())">
           <advice name="interceptGetDeclaredMethods" aspect="mypackage.MyReflectionAspect" ></advice>
       </bind>
    

     

    Bind the interceptGetMethods advice to Class.getDeclaredMethods() calls:

       <bind pointcut="call(* java.lang.Class->getMethods())">
           <advice name="interceptGetMethods" aspect="mypackage.MyReflectionAspect" ></advice>
       </bind>
    

     

     

    Fields

     

    JBoss AOP adds only private fields to advised classes, no public ones, so we only need to intercept the "declared" versions of the get field methods i.e. Class.getDeclaredFields() and Class.getDeclaredField().

     

     

    Bind the interceptGetDeclaredFields advice to Class.getDeclaredFields() calls:

       <bind pointcut="call(* java.lang.Class->getDeclaredFields())">
           <advice name="interceptGetDeclaredFields" aspect="mypackage.MyReflectionAspect" ></advice>
       </bind>
    

     

    Bind the interceptGetDeclaredField advice to Class.getDeclaredField() calls:

       <bind pointcut="call(* java.lang.Class->getDeclaredField(..))">
           <advice name="interceptGetDeclaredField" aspect="mypackage.MyReflectionAspect" ></advice>
       </bind>