포인트컷 재사용


공통 포인트컷만 모아놓은 애스펙트 작성를 작성합니다. 예를들어 MyPointcuts.

다른 애스펙트에서는 MyPointcuts.somePointcut() 처럼 static하게 액세스하여 참조합니다.


@Aspect

public class MyPointcuts {

 @Pointcut("within(my..On*Listener+) && execution(!private !static * on*(..) throws !Exception)")

 public void eventListenerMethods() {}

}


@Aspect

public class MyAspect {

    @Around("my.MyPointcuts.eventListenerMethods()")

    public Object handleListenerException(final ProceedingJoinPoint pjp) {

        try {

            return pjp.proceed();

        } catch (final Throwable e) {

            exceptionHandler.handle(e);

            return null;

        }

    }

}



어드바이스 재사용

abstract 포인트컷을 만들고 그 포인트컷을 사용하는 어드바이스를 작성합니다. 애스펙트를 abstract로 선언해야 합니다(여전히 @Aspect 어노테이션 필요함).


@Aspect

public abstract class MyAspect {

 @Pointcut("")

 protected abstract void toOverridePointcut(); 


 @After("toOverridePointcut()")

 public void myAdvice() {

    ... ...

 }

 ...

}


하위 애스펙트에서 abstract 포인트컷을 구현합니다.


@Aspect

public class YourAspect extends MyAspect {

 @Pointcut("within(android.app.Activity+) && execution(void onCreate())")

 protected void toOverridePointcut() {}


 ... ...

}


신고
Posted by 에코지오

댓글을 달아 주세요

RoboGuice 사용환경에서 AspectJ의 aspect 클래스에 모듈을 injection하는 방법입니다.



방법1. static 방식으로 injection


(1) 애스펙트 클래스에서 static 멤버변수로 선언

주입할 모듈을 static 멤버변수로 선언합니다.


 @Inject protected static ContextScopedProvider<T> tProvider; // T는 @ContextSingleton이어야함

 @Inject protected static ExceptionHandler exceptionHandler;//Singleton


(2) Guice 모듈 설정에서 static injection 처리

configure() 메소드에서 requestStaticInjection 메소드를 통해 주입합니다.


requestStaticInjection(ExceptionHandlingAspect.class);


그러나 이 방법은 권장하지 않습니다. Guice에서도 static injection은 deprecated될 것이라고 합니다.

http://code.google.com/p/google-guice/wiki/AvoidStaticState



방법 2. aspect 객체를 구하여 injection


aspect는 AspectJ에 의해 인스턴스화되며 우리가 직접 생성할 수 없습니다. 대부분의 경우 aspect는 싱글턴 객체이며, AspectJ는 싱글턴 aspect 객체를 참조할 수 있는 Aspects.aspectOf() 메소드를 제공합니다.


(1) 주입할 모듈을 애스펙트 클래스에 보통의 멤버변수로 선언


 @Inject protected ExceptionHandler exceptionHandler;


(2) Guice 모듈 설정에서 requestInjection을 통해 injection 처리


requestInjection(org.aspectj.lang.Aspects.aspectOf(ExceptionHandlingAspect.class));


참고:

신고
Posted by 에코지오

댓글을 달아 주세요

AspectJ 문서에는 아래와 같이 @within()과 @annotation()에 대해 설명합니다.



즉, Anno라는 어노테이션에 대해서(제가 제대로 해석했다면...)


- @within(Anno) : Anno 어노테이션을 갖는 타입(클래스) 안에 정의된 코드와 관련된 조인포인트

- @annotation(Anno) : 조인포인트 대상이 Anno 어노테이션을 갖는 조인포인트


http://whiteship.tistory.com/379 에서는 이렇게 설명합니다.


- @within(Type) : 선언된 타입에 @Type 어노테이션이 붙어있을 때 그 객체의 모든 execution Join point를 나타냅니다.

- @annotation(Type) : 실행되는 메소드에 @Type 어노테이션이 붙어있을 때 그 메소드의 execution Join point를 나타냅니다.


http://www.egovframe.org/wiki/doku.php?id=egovframework:rte:fdl:aop:aspectj 에서는 이렇게 설명하네요.


- @within(Transactional) : 대상 객체의 선언 타입이 @Transactional 어노테이션을 갖는 모든 결합점

- @annotation(Transactional) : 실행 메소드가 @Transactional 어노테이션을 갖는 모든 결합점



그러니까 @within()은 어노테이션이 붙은 클래스에 적용되고, @annotation()은 어노테이션이 붙은 메소드에 적용된다고 심플하게 이해하고 사용하면 될듯합니다만, 정확히 하자면 @annotation()은 조인포인트가 클래스건 메소드건 따지지 않는 것으로 보입니다.


(1) @annotation(Anno) && within(my.aop.*)

=> my.aop 패키지의 클래스 중에서 Anno 어노테이션이 붙은 클래스


(2) @annotation(Anno) && within(my.aop.*) && execution(* test*(..))
=> my.aop 패키지의 클래스에 정의된 test* 메소드 중에서 Anno 어노테이션이 붙은 메소드

(3) @annotation(Anno) && execution(* test*(..)) 
=> test* 메소드 중에서 Anno 어노테이션이 붙은 메소드

(4) @annotation(Anno) && @within(Anno) && execution(* test*(..))
=> Anno 어노테이션이 붙은 클래스의 test* 메소드 중에서 Anno 어노테이션이 붙은 메소드


대충 감이 오네요.


참고로 @annotation(Anno) && execution(* test*(..)) 포인트컷은 이렇게도 표현할 수 있습니다.

  

execution(@Anno * test*(..))




신고
Posted by 에코지오

댓글을 달아 주세요



티스토리 툴바