Recently I have been experimenting with aspect oriented programming, and the ease with which you can handle cross-cutting concerns. It’s an extremely powerful tool, allowing you to insert pointcuts throughout your code, and inject bytecode around code without polluting your source code. AspectJ provides a great deal of flexibility in the methods through which you can instrument your code.

For a live demo, take a look at the example repository over at github. The examples are using the dynamic proxy generation provided by spring. This library provides support for processing the AspectJ annotations as well as an xml-based DSL. Using this method, it is possible to easily collect arbitrary metrics, or inject logging. It can be achieved simply by adding an annotation, or a point-cut around a method.

Spring Aspect Examples

We will define an aspect which defines two sets of advice. One instruments an execution, which in this case is bound to a specific method. You are able to use interfaces here, or concrete classes. The other applies instrumentation to an annotation. This allows you to attach an annotation to any spring-managed bean, and all calls to the advised methods will be instrumented. The following code demonstrates a spring @Aspect.

@Aspect
@Component
public class ExampleAspect {
    private Logger log;

    public ExampleAspect(Logger log) {
        this.log = log;
    }

    @Around("execution(* uk.co.michaeloldroyd.example.ExampleController.exampleRequest(..))")
    public Object aspectAroundMethod(ProceedingJoinPoint pjp) throws Throwable {
        log.info("Entering {}", pjp.getClass());
        Object result = pjp.proceed();
        log.info("After {}", pjp.getClass());
        return result;
    }

    @Around("@annotation(exampleAnnotation)")
    public Object aspectAroundAnnotation(ProceedingJoinPoint pjp, ExampleAnnotation exampleAnnotation) throws Throwable {
        log.info("Entering {}", pjp.getClass());
        Object result = pjp.proceed();
        log.info("After {}", pjp.getClass());
        return result;
    }
}

Annotation-based Aspect

Assuming the controller below was component scanned, the call to SomeClassWithAspectedMethodCall.aspectedMethodCall() would be instrumented during object construction;

@Component
class ExampleController {
  SomeClassWithAspectedMethodCall thing;
  public ExampleController(SomeClassWithAspectedMethodCall thing) {
    thing.aspectedMethodCall(); // This would work
  }
}

@Component
class SomeClassWithAspectedMethodCall {
  @ExampleAnnotation
  public boolean aspectedMethodCall() {
    return true;
  }
}

Execution-based Aspect

Assuming a web endpoint is hit, the call from the servlet to the mapped method below would be instrumented;

@Component
class ExampleController {
  @RequestMapping("/")
  public void exampleRequest(SomeClassWithAspectedMethodCall thing) {
    return; // This would work
  }
}

Internal method calls

Spring AOP support requires that that aspected instances are spring beans managed by the IoC container. The limitation to this approach can be demonstrated as below;

@Component
class SomeComponent {
  public SomeComponent() {
    annotatedMethodCall(); // This won't work
  }
  @ExampleAnnotation
  public boolean annotatedMethodCall() {
    return true;
  }
}

As you can see from the examples, aspect oriented programming can provide clean way to decouple your cross-cutting concerns from implementation. I find this approach to be a great tool in any programmer’s toolkit, and look forward to exploring AspectJ further.

Michael is a Software Engineer working in the North West of England. Michael spends his days building hand-crafted PHP applications. Rumours of his super-hero status are currently unconfirmed. He savours his victories when solving difficult programming challenges; occasionally writing about them here, on his personal blog.