While AOP works fine for normal access to fields, methods and constructors, there are some problems with using the Reflection API for this using JBoss. The problems are:
To address the issues with interceptors not being invoked when you use reflection, we have provided a reflection aspect. You bind it to a set of caller pointcuts, and it mounts the pre-defined interceptor/aspect chains. The jboss-aop.xml entries are:
<aspect class="org.jboss.aop.reflection.ReflectionAspect" scope="PER_VM"/> <bind pointcut="call(* java.lang.Class->newInstance())"> <advice name="interceptNewInstance" \ aspect="org.jboss.aop.reflection.ReflectionAspect"/> </bind> <bind pointcut="call(* java.lang.reflect.Constructor->newInstance(java.lang.Object[]))"> <advice name="interceptNewInstance" \ aspect="org.jboss.aop.reflection.ReflectionAspect"/> </bind> <bind pointcut="call(* java.lang.reflect.Method->invoke(java.lang.Object, java.lang.Object[]))"> <advice name="interceptMethodInvoke" \ aspect="org.jboss.aop.reflection.ReflectionAspect"/> </bind> <bind pointcut="call(* java.lang.reflect.Field->get*(..))"> <advice name="interceptFieldGet" \ aspect="org.jboss.aop.reflection.ReflectionAspect"/> </bind> <bind pointcut="call(* java.lang.reflect.Field->set*(..))"> <advice name="interceptFieldSet" \ aspect="org.jboss.aop.reflection.ReflectionAspect"/> </bind>
The ReflectionAspect class provides a few hooks for you to override from a subclass if you like. These methods described below.
protected Object interceptConstructor( Invocation invocation, Constructor constructor, Object[] args) throws Throwable;
Calls to Class.newInstance() and Constructor.newInstance() end up here. The default behavior is to mount any constructor execution or caller interceptor chains. If you want to override the behaviour, the parameters are:
protected Object interceptFieldRead( Invocation invocation, Field field, Object instance) throws Throwable;
Calls to Field.getXXX() end up here. The default behavior is to mount any field read interceptor chains. If you want to override the behaviour, the parameters are:
protected Object interceptFieldWrite( Invocation invocation, Field field, Object instance, Object arg) throws Throwable;
Calls to Field.setXXX() end up here. The default behavior is to mount any field write interceptor chains. If you want to override the behaviour, the parameters are:
protected Object interceptMethod( Invocation invocation, Method method, Object instance, Object[] args) throws Throwable;
Calls to Method.invoke() end up here. The default behavior is to mount any method caller interceptor chains (method execution chains are handled correctly by default). If you want to override the behaviour, the parameters are:
The ReflectionAspect also helps with getting rid of the JBoss AOP "plumbing" information. You bind it to a set of caller pointcuts, using the followingjboss-aop.xml entries :
<bind pointcut="call(* java.lang.Class->getInterfaces())"> <advice name="interceptGetInterfaces" \ aspect="org.jboss.test.aop.reflection.ReflectionAspectTester"/> </bind> <bind pointcut="call(* java.lang.Class->getDeclaredMethods())"> <advice name="interceptGetDeclaredMethods" \ aspect="org.jboss.test.aop.reflection.ReflectionAspectTester"/> </bind> <bind pointcut="call(* java.lang.Class->getDeclaredMethod(..))"> <advice name="interceptGetDeclaredMethod" \ aspect="org.jboss.test.aop.reflection.ReflectionAspectTester"/> </bind> <bind pointcut="call(* java.lang.Class->getMethods())"> <advice name="interceptGetMethods" \ aspect="org.jboss.test.aop.reflection.ReflectionAspectTester"/> </bind> <bind pointcut="call(* java.lang.Class->getMethod(..))"> <advice name="interceptGetMethod" \ aspect="org.jboss.test.aop.reflection.ReflectionAspectTester"/> </bind> <bind pointcut="call(* java.lang.Class->getDeclaredFields())"> <advice name="interceptGetDeclaredFields" \ aspect="org.jboss.test.aop.reflection.ReflectionAspectTester"/> </bind> <bind pointcut="call(* java.lang.Class->getDeclaredClasses())"> <advice name="interceptGetDeclaredClasses" \ aspect="org.jboss.test.aop.reflection.ReflectionAspectTester"/> </bind> <bind pointcut="call(* java.lang.Class->getDeclaredField(..))"> <advice name="interceptGetDeclaredField" \ aspect="org.jboss.test.aop.reflection.ReflectionAspectTester"/> </bind>
This way the calls to Class.getMethods() etc. only return information that is present in the "raw" class, by filtering out the stuff added to the class by JBoss AOP.