« The New Holy Trinity | Main | Event Driven Architecture »

March 08, 2005

Ramnivas on annotations, and @Singleton

I was going to write up the @RaisesEvent stuff I showed at TSSS last week after seeing Gregor Hohpe's talk. Maybe I'll get to that tonight. However, I just saw Ramnivas Laddad's blog entry on annotations and couldn't resist interrupting the intended schedule to knock out a quick prototype.

Ramnivas suggests using an APT (annotation processing tool) to support an annotation @Singleton:

@Retention(RetentionPolicy.RUNTIME) public @interface Singleton { public SingletonKind value() default SingletonKind.Lazy; } public enum SingletonKind { Lazy, // create the singleton instance upon first use Eager; // create the singleton instance as soon as possible }

(I added the runtime retention annotation, the rest of the code is Ramnivas').

So the question is of course, can you implement this in AspectJ 5 without needing to write a custom APT?

Turns out the answer is yes :) Here's my aspect:

public aspect SingletonManager pertypewithin(@Singleton *) { Object _instance = null; /** use a static inner aspect as we need to advise call jps * that happen outside of the pertypewithin type... * (and the implicit && within(T) would exclude them) */ static aspect SingletonManagerHelper { pointcut singletonCreation() : call((@Singleton *).new(..)); Object around() : singletonCreation() { Class clazz = thisJoinPoint.getSignature().getDeclaringType(); SingletonManager mgr = SingletonManager.aspectOf(clazz); if (mgr._instance == null) { mgr._instance = proceed(); } return mgr._instance; } } // Eager instantiation support after(Singleton singleton) returning : staticinitialization(@Singleton *) && @annotation(singleton) { if (singleton.value() == SingletonKind.Eager) { try { _instance = thisJoinPoint .getSignature().getDeclaringType().newInstance(); } catch (IllegalAccessException illEx) { ; // nothing we can do - default cons not visible } catch (InstantiationException instEx) { ; // nothing we can do } } } }

I have two simple classes:

@Singleton(SingletonKind.Eager) public class EagerSingleton { static public boolean instanceCreated = false; public EagerSingleton() { instanceCreated = true; } } @Singleton(SingletonKind.Lazy) public class LazySingleton { }

These classes are used by my (passing) test cases:

public class TestSingletonSupport extends TestCase { public void testLazySingleton() { LazySingleton l1 = new LazySingleton(); LazySingleton l2 = new LazySingleton(); assertEquals("Should be a singleton",l1,l2); } public void testEagerSingleton() { assertTrue("EagerSingleton already created", EagerSingleton.instanceCreated); } }

I think this is the first time I've ever used an inner aspect of an aspect! Happy hacking....

Posted by adrian at March 8, 2005 05:11 PM [permalink]

Comments

Interesting!

This is the first time, I am seeing a use case for nested aspect, too.

Posted by: Ramnivas Laddad at March 11, 2005 06:16 AM

Isn't the inner aspect missing a syncronised block?
Just for the lazy variant ..

Posted by: Serban Draganescu [TypeKey Profile Page] at October 12, 2009 09:29 PM

Post a comment

Thanks for signing in, . Now you can comment. (sign out)

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)


Remember me?