JBoss.org Community Documentation
Let's take a look at how you can use method annotations with AOP. Using annotations and AOP together and applying this to a method is very analogous to using Java's synchronized keyword with a method. When you tag a method as synchronized, you are telling the JVM that you want that method to behave in a special way when it is invoked. Annotations allow you to define new keywords that you want to have trigger your own special custom behavior. AOP gives you the ability to encapsulate this behavior and weave it into the execution of the method.
Let's say we want to add a new syntax that will allow us to fire void
methods in the
background, in another
thread, if they are tagged as @Oneway
. Using this new syntax would look like this:
import org.jboss.aspects.Oneway; public class Foo { @Oneway public static void someMethod() {...} public static void main(String[] args) { someMethod(); // executes in background } }
When someMethod()
is invoked within main, it will run asynchronously so that the code in main is free to do
ther tasks in parallel.
To implement this functionality, the first thing that must be done is to define the new Java syntax for our
@Oneway
tag within an annotation.
package org.jboss.aspects; import java.lang.annotation.ElementType; import java.lang.annotation.Target; @Target({ElementType.METHOD}) public @interface Oneway {}
Simple enough. The @Target
tag allows you to narrow down where the annotation is allowed to
be applied. In this case, our @Oneway annotation can only be applied to a method. Remember, this is all pure
100 percent Java that is available in J2SE 5.0.
The next thing we have to do is to define an aspect class that will encapsulate our @Oneway
behavior.
package org.jboss.aspects; public OnewayAspect { private static class Task implements Runnable { private MethodInvocation invocation; public Task(MethodInvocation invocation) { this.invocation = invocation; } public void run() { try { invocation.invokeNext(); } catch (Throwable ignore) { } } } public Object oneway(MethodInvocation invocation) throws Throwable { MethodInvocation copy = invocation.copy(); Thread t = new Thread(new Task(copy)); t.setDaemon(false); t.start(); return null; } }
The aspect is simple enough. The oneway() method copies the invocation, creates a thread, fires off the complete invocation in the background, and returns. We could imagine a more sophisticated example using some of the new Executors within the J2SE 5.0 java.util.concurrent package, but hopefully this code illustrates how you could build on this example to implement more complete implementations.
The last thing that must be done is to specify the pointcut expression that will trigger the application of the
OnewayAspect
when the @Oneway
annotation is declared on a method.
<aop> <aspect class="org.jboss.aspects.OnewayAspect"/> <bind pointcut="execution(void *->@org.jboss.Oneway(..))"> <advice name="oneway" aspect="org.jboss.aspects.OnewayAspect"/> </bind> </aop>
The pointcut expression states that any void method that is tagged as @Oneway
should have
the OnewayAspect.oneway()
method executed before it itself executes. With the annotation,
aspect, and pointcut expression now defined, the @Oneway syntax is now usable in your application. A simple,
clean, easy way of extending the Java language!