Singletons with AspectJ

I stumbled upon this post (german) that shows how to implement the singleton pattern with AspectJ. Although you may want to use dependency injection with Spring or Guice, there might be (hopefully rare) occasions on which you opt for this solution. In this post we’ll check out how to do this with AspectJ 5.

The Eclipse project with the sample code for this post can be downloaded as tar.gz or zip; make sure to install the AspectJ Development Tools. You can browse the code online here.

Classic singleton pattern

The traditional way to implement a singleton consists of a private constructor, a static final field that holds the instance of the class and a getInstance method that returns this instance. In Java this looks like this:

public class Singleton {
  private static final Singleton singleton = new Singleton();
 
  private Singleton() {}
 
  public static Singleton getInstance() {
    return singleton;
  }
}

This gets really annoying if you’ve got this code more than once in your application. So lets have a look at an aspect that resembles this functionality.

Implementing the aspect

If you’ve got more than one singleton in your application you may think of a singleton as a crosscutting concern. Consequently, you’ll write an aspect that intercepts calls to the constructor of the singleton class and instead of creating a new instance every time you’ll return the instance that was created at the very fist call to the constructor.

The logic for this idea can be expressed with the following code fragment:

Map<Class<?>, Object> singletons;
...
Class<?> singletonClass = joinPoint.getSignature().getDeclaringType();
Object singletonObject = this.singletons.get(singletonClass);
if (singletonObject == null) {
  singletonObject = joinPoint.proceed();
  this.singletons.put(singletonClass, singletonObject);
}
return singletonObject;

We have a map that holds references to all instances of our singleton classes. The method that intercepts the calls to the constructor of a given class stores a reference to the created instance in the map and returns that instance on the following calls to the constructor of the same class.

So, you can do the following in the code and will get references to the same instance of the class:

Singleton s1 = new Singleton();
Singleton s2 = new Singleton();
// s1 == s2

All that’s left to do, is to define a pointcut and to remove the boilerplate code from the singleton class. A pointcut can look like this:

@Pointcut("call(*.SingletonAop.new(..))")
protected void singletons() {}

Conclusion

We implemented a solution for the singleton pattern with AspectJ 5. The used approach caches the instances of the singleton classes and returns the cached ones once the constructor has been called for the first time. Note: to simplify matters we left out thread safety.

Although this solution is somehow elegant and may be useful to clean up some code in a legacy system, we should consider the following points:

Can we use a dependency injection framework?
Spring uses singletons by default and with Guice you can mark singletons with the @Singleton annotation. So, we might want to choose one of these frameworks instead of implementing this functionality on our own.
Java skill of the team?
The presented implementation should be well documented, because nothing would be more irritating than a novice developer in your team who doesn’t know about this magic behind the scenes and relies on different instances of the singleton class (“I thought new would be doing…”).

There are other solutions available to this problem. So, I wouldn’t recommend to implement this kind of caching with AspectJ.

1 comment so far ↓

Leave a Comment