AspectJ

Автор: Ржевский Дмитрий

Язык AspectJ предоставляет дополнительные возможности. Давайте посмотрим как это можно использовать реализуя привычные паттерны на языка Java. Синлтон - позволяет создать и использовать только один объект данного класса в JVM.
public class Singleton {
  private static final Singleton singleton = new Singleton();
 
  private Singleton() {}
 
  public static Singleton getInstance() {
    return singleton;
  }
}
А теперь давайте улучшим Этот код. Его можно улучшить на столько что всю логику вынести в отдельную библиотеку.
1) Создадим аннотацию-маркер. Этой аннотацией будем помечать класс котороый хотим сделать синглтоном.
     public @interface Singlton {
     }


    
2) Напишем аспект. Аспект хранит в HashTable все созданные инстансы синглтонов (по одному для каждого класса). Все вызовы конструкторов синглтонов (pointcut callConstructor) замещаются на вызов getInstance. В getInstance проверяется есть ли синглтон для данного класса в HashTable. Если есть -то он возващается. если не- создаётся, ложится в HashTable и возвращается вновь созданный инстанс.

        /**
         * Keep all singltons in singletonMap. Returned instance from map instead constructor call .
         */
        @Aspect
        public class SingltonAspect {

            private final Map<Class<?>, Object> singletonMap = new HashMap<Class<?>, Object>();

            /**match  contructor call for type annotated with @Singlton.*/
            @Pointcut("call((@Singlton *).new(..))")
            void callConstructor() {
            }
            /**This advice called instead Singlton's  constuctor call.*/
            @Around("callConstructor()")
            public Object getInstance(final ProceedingJoinPoint thisJoinPoint) throws Throwable {
                final Class singletonClass = thisJoinPoint.getSignature().getDeclaringType();
                Object singletonObject = this.singletonMap.get(singletonClass);
                if (singletonObject == null) {
                    singletonObject = thisJoinPoint.proceed();
                    this.singletonMap.put(singletonClass, singletonObject);
                }
                return singletonObject;
            }

        }

    
Теперь давайте проверим как это работает:

        /**
         * Only one instance of this class allowed.
         */
        @Singlton
        public class MySinglton {
        }

    
       MySinglton singlton1 = new MySinglton();
       MySinglton singlton2 = new MySinglton();
       System.out.println("singlton1 == singlton2 : " + (singlton1==singlton2));
    
Последний кусок кда выведет на экран singlton1 == singlton2 : true

Скачать код

Ссылки

  1. http://ru.wikipedia.org/wiki/Одиночка_(шаблон_проектирования)
  2. http://www.christianschenk.org/blog/singletons-with-aspectj