ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 스프링4.0 - AOP : @Aspect 기반
    웹프로그래밍/spring 2018. 7. 16. 21:10

    XML 스키마 설정 대신에 @Aspect 어노테이션을 클래스에 적용한다.



    1. Before Advice

    import org.aspectj.lang.annotation.Aspect;

    import org.aspectj.lang.annotation.Before;


    @Aspect

    public class ArticleCacheAspect {


    private Map<Integer, Article> cache =new HashMap<Integer, Article>();

    @Around("execution(public * *..ReadArticleService.*(..))")

    public Article cache(ProceedingJoinPoint joinPoint) throws Throwable {

    Integer id = (Integer) joinPoint.getArgs()[0];

    Article article = cache.get(id);

    if(article != null) {

    System.out.println("[ACA] 캐시에서 Article["+id+"] 구함");

    return article;

    }

    Article ret = (Article) joinPoint.proceed();

    if(ret != null) {

    cache.put(id, ret);

    System.out.println("[ACA] 캐시에서 Article["+id+"] 추가함");

    }

    return ret;

    }

    }





    2. After Returning Advice

    Advice 대상 객체가 리턴한 값을 사용하고 싶다면

    @AfterReturning에 returning 속성을 넣고

    구현 메서드의 파라미터로 세팅하면 그 리턴 값을 전달 받을 수 있다.


    import org.aspectj.lang.annotation.AfterReturning;

    import org.aspectj.lang.annotation.Aspect;


    @AfterReturning(pointcut="대상 객체의 클래스 경로" returning="ret")

    public void afterReturning(Object ret) {

    //공통기능

    }


    만약 리턴 값이 특정 객체 타입인 경우도 가능


    @AfterReturning(pointcut="대상 객체의 클래스 경로" returning="ret")

    public void afterReturning(Article ret) {

    //공통기능

    }


    대상 객체의 정보가 필요한 경우


    @AfterReturning(pointcut="대상 객체의 클래스 경로" returning="ret")

    public void afterReturning(JoinPoint joinPoint, Object ret) {

    //공통기능

    }





    3.After Throwing Advice

    import org.aspectj.lang.annotation.AfterThrowing;

    import org.aspectj.lang.annotation.Aspect;


    @Aspect

    public class LoggingAspect{


    @AfterThrowing("경로")

    public void afterThrowing() {

    //공통기능

    }


    대상 객체의 메서드가 발생시킨 익셉션 객체에 접근하려면 @AfterThrowing에 throwing 속성을 추가한다.

    그리고 Advice 구현 메서드에 파라미터를 추가한다.


    @AfterThrowing(pointcut="경로" throwing="ex")

    public void afterThrowing(Throwable ex) {

    //공통기능

    }


    Throwable이나 Exception 이외에 특정 타입의 익셉션을 넣어서 익셉션 발생을 특정할 수도 있다.


    @AfterThrowing(pointcut="경로" throwing="ex")

    public void afterThrowing(ArticleNotFoundException ex) {

    //공통기능

    }


    대상 객체의 정보가 필요한 경우


    @AfterThrowing(pointcut="경로" throwing="ex")

    public void afterThrowing(JoinPoint joinPoint, Exception ex) {

    //공통기능

    }



    4.After Advice

    import org.aspectj.lang.annotation.After;

    import org.aspectj.lang.annotation.Aspect;


    @Aspect

    public class LoggingAspect {


    @After("경로")

    public void afterFinally() {

    //공통기능

    }



    대상 객체의 정보가 필요한 경우


    @After("경로")

    public void afterFinally(JoinPoint joinPoint) {

    //공통기능

    }



    5.Around Advice

    Around Advice구현 메서드는 org.aspectj.lang.ProceedingJoinPoint 타입을 첫 번째 파라미터로 지정해야 한다. 아니면 익셉션 발생

    ProceedingJoinPoint의 proceed()로 프록시 대상 객체의 실제 메서드를 호출 하므로,

    joinpoint.proceed() 전, 후에 공통 기능을 구현한다. 


    import java.util.HashMap;

    import java.util.Map;


    import org.aspectj.lang.ProceedingJoinPoint;

    import org.aspectj.lang.annotation.Around;

    import org.aspectj.lang.annotation.Aspect;


    import spring.chap06.board.Article;


    @Aspect

    public class ArticleCacheAspect {


    private Map<Integer, Article> cache =new HashMap<Integer, Article>();

    @Around("execution(public * *..ReadArticleService.*(..))")

    public Article cache(ProceedingJoinPoint joinPoint) throws Throwable {

    Integer id = (Integer) joinPoint.getArgs()[0];

    Article article = cache.get(id);

    if(article != null) {

    System.out.println("[ACA] 캐시에서 Article["+id+"] 구함");

    return article;

    }

    Article ret = (Article) joinPoint.proceed();

    if(ret != null) {

    cache.put(id, ret);

    System.out.println("[ACA] 캐시에서 Article["+id+"] 추가함");

    }

    return ret;

    }

    }