ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Aspect-Oriented Annotations Aspect-Oriented Annotations

by Bill Burke, coauthor of Enterprise JavaBeans, 4th Edition
03/02/2005

Annotations are one of the new language features in J2SE 5.0, and allow you to attach metadata onto any Java construct. Meanwhile, Aspect-Oriented Programming (AOP) is a fairly new technology that makes it easier for you to encapsulate behavior that is usually messier, harder, or impossible to do with regular object-oriented (OO) techniques. Together, they make a new powerful combination that gives framework developers a more expressive way of providing their APIs. This article dives into combining these technologies using the JBoss AOP framework in various coding examples to show how you can use this combination to actually extend the Java language.

Annotation Overview

First let's give a brief overview of the two technologies. Annotations are new to JDK 5.0 and are defined in detail in the JSR-175 specification. They allow you to define metadata in a typesafe way and apply it to a class, method, constructor, field, or parameter. For those of you familiar with XDoclet, annotations will be very intuitive to you in that you are used to declaring tags to generate code. The main difference between the two is that annotations are a typed part of the Java language, while XDoclet tags can be mistyped and are harder to create. I like to work with examples, so let's show a simple one.

To define an annotation, all you need to do is declare a special kind of Java interface.

Orange.java

package org.jboss.colors;

public @interface Orange {}

After defining this interface, you can use it to give more description to your Java elements.

Foo.java

package org.jboss.examples;

public class Foo
{
   @Orange void someMethod();

   @Orange private int someField;
}

So what can use use annotations for? Some people envision using annotations for code generation and a replacement for XDoclet. Others, like the J2EE and EJB 3.0 expert groups, see it as a replacement for deployment descriptors. This article talks about how annotations can be used with AOP.

AOP Overview

There are many articles and books that explain what AOP actually is, such as Graham O'Regan's ONJava article "Introduction to Aspect-Oriented Programming." I'll give a quick overview in this article, but I encourage you to do more research online.

AOP is about the clean separation and encapsulation of cross-cutting concerns. Sounds academic, I know, but bear with me for a minute. A cross-cutting concern is the code sprinkled throughout your codebase, code that has structure, but cannot be organized or declared using traditional OO techniques. AOP is best explained by example, so let's walk through one to more clearly understand what AOP actually is.

Let's say you wanted to add code to an application to measure the amount of time it would take to invoke a particular Java method. The code could look something like this:

public class BankAccount
{
  public void withdraw(double amount)
  {
    long startTime = System.currentTimeMillis();
    try
    {
      // Actual method body...
    }
    finally
    {
      long endTime = System.currentTimeMillis() - startTime;
      System.out.println("withdraw took: " + endTime);
    }
  }
}

While this code works just fine, there are a few problems with this approach:

  1. It's extremely difficult to turn metrics on and off, as you have to manually add the code in the try/finally block to each and every method or constructor you want to benchmark.
  2. The profiling code really doesn't belong sprinkled throughout your application code. It makes your code bloated and harder to read, as you have to enclose the timings within a try/finally block.
  3. If you wanted to expand this functionality to include a method or failure count, or even to register these statistics to a more sophisticated reporting mechanism, you'd have to modify a lot of different files (again).

Metrics present a perfect, tiny, small example of what a cross-cutting concern is. JBoss AOP provides a simple way of encapsulating and applying such a concern in an implicit way so that something like metrics code does not pollute your codebase. Let's dive into JBoss AOP a bit to see how you can do this.

To encapsulate metrics functionality using JBoss AOP, you first need to define an aspect that specifies the metrics behavior.

public class Metrics
{
   public Object profile(MethodInvocation invocation) throws Throwable
   {
      long startTime = System.currentTimeMillis();
      try
      {
         return invocation.invokeNext();
      }
      finally
      {
         long endTime = System.currentTimeMillis() - startTime;
         java.lang.reflect.Method m = invocation.getMethod();
         System.out.println("method " + m.toString() +
                            " time: " + endTime + "ms");
      }  
   }
}

An aspect is just a plain Java class that has methods in it that define the behavior you want to attach to your object model. The signature of these methods must return a java.lang.Object and must have one (and only one) argument of a JBoss AOP invocation object, which is used to encapsulate the method, constructor, or field invocation. The method name can be anything you want and is referenced when you actually bind the aspect to a piece of your code.

The next thing to do is to actually apply the aspect to the points in your program where you want it to profile a method's execution. Most AOP frameworks provide a pointcut expression language where you can define where you want certain aspect behavior to be attached. Here's how to do this in JBoss AOP.

jboss-aop.xml

<aop>
   <aspect class="Metrics"/>

   <bind pointcut="execution(public void BankAccount->withdraw(double amount))">
      <advice name="profile" aspect="Metrics"/>
   </bind>
</aop>

With the definition of the aspect in Metrics.java and the pointcut definition within jboss-aop.xml, the metrics code is now applied implicitly and transparently to the BankAccount.withdraw() method and can easily be removed when the profiling code is no longer needed by the application.

For more information on JBoss AOP, check out the tutorial that comes with the distribution. It has about 20 example programs that walk you through how to use the JBoss AOP framework.

Pages: 1, 2, 3

Next Pagearrow