티스토리 뷰

728x90

1. 이 포스트는 Spring AOP with Java Config 의 연장이다.

 

2. 포인트 컷 정의에서 parameter에 들어갈 pattern을 wildcard를 통해 지정할 수 있다.

  2-1 () parameter가 없는 메소드 정의

  2-2 (*) 하나의 parameter를 받는데 모든 타입을 다 허용한다.

  2-3 (..) 어떤 타입의 parameter형태도 다 허용한다.

 

3. 각 wild 카드에 해당하는 예제들

  3-1 모든 리턴 타입을 허용하는 add로 시작하고 parameter가 없는 메소드를 허용하는 예제

    3-1-1 이미 바로 전 포스트에서 보여 주었다. 

// AOP Advice 클래스
@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("\nExecuting @Before advice on * add*()");
  }
}

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

// dummy component 1
@Component
public class AccountDAO {
  public void addAccount() {
    System.out.println(getClass() + ": with No Parameter Doing my DB work: Adding an account\n");
  }
  
  public void addAccount(Account account) {
    System.out.println(getClass() + ": with Account Parameter. Doing my DB work: Adding an account\n");
  }
}

// dummy component 2
@Component
public class MembershipDAO {

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



// 결과

Executing @Before advice on * add*()
class pe.pilseong.spring_aop_review.dao.AccountDAO: with No Parameter Doing my DB work: Adding an account

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


Executing @Before advice on * add*()
class pe.pilseong.spring_aop_review.dao.MembershipDAO: Doing my DB work: Adding an account


Executing @Before advice on * add*()
class pe.pilseong.spring_aop_review.dao.MembershipDAO: Doing my DB work: Adding a good account

  3-2 모든 리턴 타입을 허용하는 한 개의 특정한 타입의 parameter를 허용하는 예제

    3-2-1 반드시 parameter type에는 패키지 경로를 포함하는 fully qualified name을 사용해야 한다.

    3-2-2 그렇지 않으면 class type을 찾을 수 없다고 IllegalArgumentException이 발생한다.

@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*())")

  @Before(value="execution(* add*(pe.pilseong.spring_aop_review.Account))")
  public void beforeAddAccountAdvice() {
    System.out.println("\nExecuting @Before advice on * add*(Account)");
  }
}

// 결과
class pe.pilseong.spring_aop_review.dao.AccountDAO: with No Parameter Doing my DB work: Adding an account


Executing @Before advice on * add*(Account)
class pe.pilseong.spring_aop_review.dao.AccountDAO: with Account Parameter. 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

  3-3 '..' wildcard의 활용

    3-3-1 Account와 boolean을 받는 메소드를 추가하고 우선 3-2의 경우로 실행하면 아래와 같은 결과가 나온다.

    3-3-2 당연히 Account를 파라메터로 받는 메소드만 Advice가 실행됨을 알 수 있다.

@Component
public class AccountDAO {
  public void addAccount() {
    System.out.println(getClass() + ": with No Parameter Doing my DB work: Adding an account\n");
  }
  
  public void addAccount(Account account) {
    System.out.println(getClass() + ": with Account Parameter. Doing my DB work: Adding an account\n");
  }
  
  // 추가 메소드
  public void addAccount(Account account, boolean flag) {
    System.out.println(getClass() + ": with Account, boolean Parameter. Doing my DB work: Adding an account\n");
  }
}

// 메인 클래스
public class App {
  public static void main(String[] args) {
    AnnotationConfigApplicationContext context = 
        new AnnotationConfigApplicationContext(JavaConfig.class);
    
    AccountDAO accountDAO = context.getBean("accountDAO", AccountDAO.class);
    accountDAO.addAccount();
    
    Account account = new Account();
    accountDAO.addAccount(account);
    
    // 추가한 메소드 call
    accountDAO.addAccount(account, true);
    
    MembershipDAO membershipDAO = context.getBean("membershipDAO", MembershipDAO.class);
    
    membershipDAO.addAccount();
    membershipDAO.addGoodAccount();
    
    context.close();
  }
}


// 결과
class pe.pilseong.spring_aop_review.dao.AccountDAO: with No Parameter Doing my DB work: Adding an account


Executing @Before advice on * add*(Account)
class pe.pilseong.spring_aop_review.dao.AccountDAO: with Account Parameter. Doing my DB work: Adding an account

class pe.pilseong.spring_aop_review.dao.AccountDAO: with Account, boolean Parameter. 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

    3-3-2 Account 파라메터 옆에 '..' 와일드 카드를 추가한 경우

      3-3-2-1 Account를 받는 것 뿐만 아니라 Account, boolean을 받는 메소드도 @Before advice가 실행되었다.

@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*())")
//  @Before(value="execution(* add*(pe.pilseong.spring_aop_review.Account))")

  @Before(value="execution(* add*(pe.pilseong.spring_aop_review.Account, ..))")
  public void beforeAddAccountAdvice() {
    System.out.println("\nExecuting @Before advice on * add*(Account)");
  }
}


// 결과
class pe.pilseong.spring_aop_review.dao.AccountDAO: with No Parameter Doing my DB work: Adding an account


Executing @Before advice on * add*(Account, ..)
class pe.pilseong.spring_aop_review.dao.AccountDAO: with Account Parameter. Doing my DB work: Adding an account


Executing @Before advice on * add*(Account, ..)
class pe.pilseong.spring_aop_review.dao.AccountDAO: with Account, boolean Parameter. 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

    3-3-3 파라메터로 '..' 와일드 카드만 설정한 경우 - 모든 형태의 parameter 허용

      3-3-3 파라메터 형태와 무관하게 add로 시작하는 모든 메소드 실행 전에 @Before Advice가 실행되었다.

@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*())")
//  @Before(value="execution(* add*(pe.pilseong.spring_aop_review.Account))")
//  @Before(value="execution(* add*(pe.pilseong.spring_aop_review.Account, ..))")
  
  @Before(value="execution(* add*(..))")
  public void beforeAddAccountAdvice() {
    System.out.println("\nExecuting @Before advice on * add*(..)");
  }
}


// 실행 결과

Executing @Before advice on * add*(..)
class pe.pilseong.spring_aop_review.dao.AccountDAO: with No Parameter Doing my DB work: Adding an account


Executing @Before advice on * add*(..)
class pe.pilseong.spring_aop_review.dao.AccountDAO: with Account Parameter. Doing my DB work: Adding an account


Executing @Before advice on * add*(..)
class pe.pilseong.spring_aop_review.dao.AccountDAO: with Account, boolean Parameter. Doing my DB work: Adding an account


Executing @Before advice on * add*(..)
class pe.pilseong.spring_aop_review.dao.MembershipDAO: Doing my DB work: Adding an account


Executing @Before advice on * add*(..)
class pe.pilseong.spring_aop_review.dao.MembershipDAO: Doing my DB work: Adding a good account

  3.4 패키지를 한정 하는 방법

    3-4-1 아래 소스처럼 패키지 이름을 명시하고 클래스와 메소드 이름에 '*'를 사용하면 

    3-4-2 해당 패키지에 포함된 모든 메소드 실행시 @Before advice가 실행된다.

@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*())")
//  @Before(value="execution(* add*(pe.pilseong.spring_aop_review.Account))")
//  @Before(value="execution(* add*(pe.pilseong.spring_aop_review.Account, ..))")
//  @Before(value="execution(* add*(..))")

  @Before("execution(* pe.pilseong.spring_aop_review.dao.*.*(..))")
  public void beforeAddAccountAdvice() {
    System.out.println("\nExecuting @Before advice on pe.pilseong.spring_aop_review.dao.*.*(..)");
  }
}

    3-4-3 아래처럼 MembershipDAO에 addAccount가 아닌 이름의 메소드를 추가하였다.

@Component
public class MembershipDAO {

  public void addAccount() {
    System.out.println(getClass() + ": Doing my DB work: Adding an account\n");
  }
  
  public void addGoodAccount() {
    System.out.println(getClass() + ": Doing my DB work: Adding a good account\n");
  }
  
  // 추가된 메소드
  public void membership() {
    System.out.println(getClass() + ": Doing my DB work: membership method is doing something \n");
  }
}

    3-4-4 메인 클래스에 추가한 메소드를 실행하도록 변경 후 실행

      3-4-4-1 pe.pilseong.spring_aop_review.dao 패키지에 포함된 모든 클래스의 메소드를 호출하기 전

      3-4-4-2 @Before advice가 실행 된다.

public class App {
  public static void main(String[] args) {
    AnnotationConfigApplicationContext context = 
        new AnnotationConfigApplicationContext(JavaConfig.class);
    
    AccountDAO accountDAO = context.getBean("accountDAO", AccountDAO.class);
    accountDAO.addAccount();
    
    Account account = new Account();
    accountDAO.addAccount(account);
    
    accountDAO.addAccount(account, true);
    
    MembershipDAO membershipDAO = context.getBean("membershipDAO", MembershipDAO.class);
    
    membershipDAO.addAccount();
    membershipDAO.addGoodAccount();
    
    // 추가로 호출한 부분
    membershipDAO.membership();
    
    context.close();
  }
}

// 결과

Executing @Before advice on pe.pilseong.spring_aop_review.dao.*.*(..)
class pe.pilseong.spring_aop_review.dao.AccountDAO: with No Parameter Doing my DB work: Adding an account


Executing @Before advice on pe.pilseong.spring_aop_review.dao.*.*(..)
class pe.pilseong.spring_aop_review.dao.AccountDAO: with Account Parameter. Doing my DB work: Adding an account


Executing @Before advice on pe.pilseong.spring_aop_review.dao.*.*(..)
class pe.pilseong.spring_aop_review.dao.AccountDAO: with Account, boolean Parameter. Doing my DB work: Adding an account


Executing @Before advice on pe.pilseong.spring_aop_review.dao.*.*(..)
class pe.pilseong.spring_aop_review.dao.MembershipDAO: Doing my DB work: Adding an account


Executing @Before advice on pe.pilseong.spring_aop_review.dao.*.*(..)
class pe.pilseong.spring_aop_review.dao.MembershipDAO: Doing my DB work: Adding a good account


Executing @Before advice on pe.pilseong.spring_aop_review.dao.*.*(..)
class pe.pilseong.spring_aop_review.dao.MembershipDAO: Doing my DB work: membership method is doing something 
728x90
댓글