« 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 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.)