티스토리 뷰

728x90

0. 이 포스트는 Spring AOP with Java Config 시리즈의 연속된 내용이다.

 

1. Point Cut Expression은 어떤 메소드가 실행되어야 할지 AOP Proxy가 결정하는데 정보를 제공한다.

@Aspect
@Component
public class LoggingAspect {

//  @Before(value = "execution(public void addAccount())")
  @Before(value = "execution(public void pe.pilseong.spring_aop_review.dao.AccountDAO.addAccount())")
  public void beforeAddAccountAdvice() {
    System.out.println("\n\nExecuting @Before advice on addAccount()\n\n");
  }
}

2. 위의 소스를 보면 @Before Advice의 value에 있는 execution내에 있는 메소드 정의 부분이 point cut expression이다.

  2-1 포인터 컷 public void pe.pilseong.spring_aop_review.dao.AccountDAO.addAccount() 구성요소는

    2-1-1 접근자(modifier) - 선택사항이다. - public 

    2-1-2 리턴타입(return type) - 선택사항이다. - void

    2-1-3 Fully qualified class name (package + class이름) - 선택사항이다.

      2-1-3-1 pe.pilseong.spring_aop_review.dao.AccountDAO

    2-1-4 method name(parameter type) - 필수 사항이다. - addAccount()

    2-1-5 Exception type - 선택사항이다. - 위의 예에서는 생략되어 있다.

  2-2 point cut은 pattern으로 표현될 수 있으며 wildcard (*) 등을 통하여 다양하게 표현될 수 있다.

 

3. 위에 작성한 코드로 실행을 하면 구체적인 Type이 지정되어 있으므로 AccountDAO의 addAccount만 실행이 된다.

//결과 값은 아래와 같다.

Executing @Before advice on addAccount()


class pe.pilseong.spring_aop_review.dao.AccountDAO: Doing my DB work: Adding an account
class pe.pilseong.spring_aop_review.dao.MembershipDAO: Doing my DB work: Adding an account

4. 포인트 컷을 수정하여 리턴 타입이 void이고 모든 add로 시작하는 메소드 직전에 advice가 실행되는 예제다.

  4-1 @Before(value = "execution(public void add*())") 로 pointcut을 수정하였다.

@Aspect
@Component
public class LoggingAspect {

//  @Before(value = "execution(public void addAccount())")
  @Before(value = "execution(public void add*())")
  public void beforeAddAccountAdvice() {
    System.out.println("\n\nExecuting @Before advice on addAccount()\n\n");
  }
}

  4-2 MembershipDAO에 addGoodAccount를 추가한다.

@Component
public class MembershipDAO {

  public void addAccount() {
    System.out.println(getClass() + ": Doing my DB work: Adding an account");
  }
  
  public void addGoodAccount() {
    System.out.println(getClass() + ": Doing my DB work: Adding a good account");
  }
}

  4-3 실행파일을 아래 처럼 수정한다.

public class App {
  public static void main(String[] args) {
    AnnotationConfigApplicationContext context = 
        new AnnotationConfigApplicationContext(JavaConfig.class);
    
    AccountDAO accountDAO = context.getBean("accountDAO", AccountDAO.class);
    accountDAO.addAccount();
    
    MembershipDAO membershipDAO = context.getBean("membershipDAO", MembershipDAO.class);
    
    membershipDAO.addAccount();
    membershipDAO.addGoodAccount();
    
    
    context.close();
  }
}


// 결과 값
Executing @Before advice on addAccount()


class pe.pilseong.spring_aop_review.dao.AccountDAO: Doing my DB work: Adding an account


Executing @Before advice on addAccount()


class pe.pilseong.spring_aop_review.dao.MembershipDAO: Doing my DB work: Adding an account


Executing @Before advice on addAccount()


class pe.pilseong.spring_aop_review.dao.MembershipDAO: Doing my DB work: Adding a good account

6. 포인트 컷을 수정하여 리턴타입이 boolean이고 메소드이름이 add로 시작하는 메소드만 advice가 실행하는 예제

  6-1 포인트 컷을 아래처럼 수정한다.

@Aspect
@Component
public class LoggingAspect {

//  @Before(value = "execution(public void addAccount())")
//  @Before(value = "execution(public void add*())")
  @Before(value="execution(boolean add*())")
  public void beforeAddAccountAdvice() {
    System.out.println("\n\nExecuting @Before advice on addAccount()\n\n");
  }
}

  6-2 실행한 결과는 다음과 같다. @Before advice가 실행되지 않았음을 알 수 있다.

class pe.pilseong.spring_aop_review.dao.AccountDAO: Doing my DB work: Adding an account
class pe.pilseong.spring_aop_review.dao.MembershipDAO: Doing my DB work: Adding an account
class pe.pilseong.spring_aop_review.dao.MembershipDAO: Doing my DB work: Adding a good account

  6-3 아래 처럼 point cut을 모든 리턴타입을 포함하도록 수정하면 모든 메소드 전에 @Before가 실행된다.

@Aspect
@Component
public class LoggingAspect {

//  @Before(value = "execution(public void addAccount())")
//  @Before(value = "execution(public void add*())")
//  @Before(value="execution(boolean add*())")
  @Before(value="execution(* add*())")
  public void beforeAddAccountAdvice() {
    System.out.println("\n\nExecuting @Before advice on addAccount()\n\n");
  }
}

// 결과 값


Executing @Before advice on addAccount()


class pe.pilseong.spring_aop_review.dao.AccountDAO: Doing my DB work: Adding an account


Executing @Before advice on addAccount()


class pe.pilseong.spring_aop_review.dao.MembershipDAO: Doing my DB work: Adding an account


Executing @Before advice on addAccount()


class pe.pilseong.spring_aop_review.dao.MembershipDAO: Doing my DB work: Adding a good account

 

728x90
댓글