/** * @@billable (amount=0.05) * @@trace */ public void someMethod() { System.out.println("someMethod"); }
JBossAOP tags are defined by a double at symbol '@@' and zero or more name/value pairs. In the above example, we are declaring someMethod() to be traced and billable to an ammount of $0.05 every time it is accessed. This Java source file is run through JBossAOP's annotation compiler to generate XML. You can run this annotation compiler as an ANT taskdef or standalone. Look at build.xml to see how the taskdef is set up for annotationc.
The annotationc task is very similar to the javac taskdef. You declare <src> tags just as you would with javac. Any .java files in your sourcepath will be compiled and an XML file will be generated.
When you run the build, metadata-aop.xml is generated. Take a look at that to see how the doclet tags are mapped to XML. It is pretty straightforward.
<bind pointcut="execution(POJO->@billable(..))"> <interceptor class="BillingInterceptor"/> </bind> <bind pointcut="execution(* POJO->@billable(..))"> <interceptor class="BillingInterceptor"/> </bind>
The first binding above says that for every constructor tagged as @billable apply the BillingInterceptor. The second binding states that for any method tagged as @billable apply the BillingInterceptor. Let's now take a look at applying the tracing advice.
<bind pointcut="all(@trace)"> <interceptor class="TraceInterceptor"/> </bind>
The above states that for any field, constructor, or method tagged as @trace, apply the TraceInterceptor.
public Object invoke(Invocation invocation) throws Throwable { System.out.println("billing amount: $" + invocation.getMetaData("billable", "amount")); }
$ antIt will run the annotationc compiler on the source files to generate metadata in metadata-aop.xml, then javac the files and then run the AOPC precompiler to manipulate the bytecode, then finally run the example. Note that there are two XML aop deployment descriptors: metadata-aop.xml and jboss-aop.xml. The System Property jboss.aop.path can accept a list of files delimited by the platform classpath separator. ';' on windows ':' on unix. Running the example should produce:
run: [java] --- new POJO(); --- [java] billing amount: $0.01 [java] <<< Trace : executing constructor public POJO() [java] empty constructor [java] >>> Leaving Trace [java] --- new POJO(int); --- [java] billing amount: $0.01 [java] <<< Trace : executing constructor public POJO(int) [java] int constructor [java] >>> Leaving Trace [java] --- pojo.someMethod(); --- [java] billing amount: $0.05 [java] <<< Trace : executing method public void POJO.someMethod() [java] someMethod [java] >>> Leaving Trace [java] --- pojo.field = 55; --- [java] <<< Trace : write field name: public int POJO.field [java] >>> Leaving Trace