티스토리 뷰

728x90

1. 이 포스트는 Spring : AOP with Java Config 시리즈의 연속이다.

 

2. @Afterthrowing 타겟 메소드에서 Exception이 발생한 경우에만 실행된다.

 

3. 주된 Use case 들

  3-1 예외에 대한 로그처리

  3-2 예외상황에 대한 감사(Audit) 처리

  3-3 예외가 발생한 경우 이메일이나 SMS를 통한 알람

 

4. 아래는 boolean 변수를 사용하여 Exception을 발생시키는 예제다.

  4-1 App.java 클래스에서 triggerError변수가 true일 경우 Exception이 발생한다.

    4-1-1 이 경우 @AfterThrowing advice가 실행된다.

  4-2 triggerError가 false일 경우 정상적으로 수행되고 @AfterReturning advice가 실행된다.

// Aspect Class정의
package pe.pilseong.aop_after_returning.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

  // 타겟 메소드에서 예외가 발생한 경우에만 실행된다.
  @AfterThrowing(
    pointcut = "execution(* pe.pilseong.aop_after_returning.dao.AccountDAO.findAccounts(..))", 
    throwing = "ex"
  )
  public void afterThrowingFindAccountsAdvice(JoinPoint joinPoint, Throwable ex) {
    System.out.println("Aspect(@AfterThrowing) :: afterThrowingFindAccountsAdvice is executed after "
        + joinPoint.getSignature().toShortString());
  }

  // 정상적으로 타겟 메소드가 수행된 경우에만 실행된다.
  @AfterReturning(
    pointcut = "execution(* pe.pilseong.aop_after_returning.dao.AccountDAO.findAccounts(..))"
  )
  public void afterReturningFindAccountsAdvice(JoinPoint joinPoint) {
    System.out.println("Aspect(@AfterReturning) :: afterReturningFindAccountsAdvice is executed after "
        + joinPoint.getSignature().toShortString());
  }
}

// 더미 DAO 클래스
package pe.pilseong.aop_after_returning.dao;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Component;

import pe.pilseong.aop_after_returning.Account;

@Component
public class AccountDAO {
  private static List<Account> accounts;
  
  static {
    accounts = new ArrayList<>();
    
    accounts.add(new Account("Pilseong", "Admin"));
    accounts.add(new Account("Suel", "Admin"));
    accounts.add(new Account("Noel", "Staff"));
  }

  public List<Account> findAccounts(boolean triggerError) {
    System.out.println("findAccounts is executed");
    
    // triggerError가 true일 경우 Exception을 발생시킨다.
    if (triggerError) {
      throw new RuntimeException("Exception :: To trigger @AfterThrowing");  
    }
    
    return AccountDAO.accounts;
  }
}

// 실행 클래스
package pe.pilseong.aop_after_returning;

import java.util.List;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import pe.pilseong.aop_after_returning.config.JavaConfig;
import pe.pilseong.aop_after_returning.dao.AccountDAO;

public class App {
  public static void main(String[] args) {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(JavaConfig.class);

    AccountDAO accountDAO = context.getBean("accountDAO", AccountDAO.class);

    List<Account> accounts = null;
    // 강제적으로 발생한 예외를 처리한 try - catch 구문
    try {
      boolean triggerError = false;
      accounts = accountDAO.findAccounts(triggerError);
    } catch (Exception e) {
      System.out.println("Main App class :: " + e.getMessage());
    }

    System.out.println("\nMain App class :: ");
    System.out.println("Main App class Accounts List :: " + accounts);

    context.close();
  }
}

// 실행 결과 : triggerError = false 경우 - 정상적인 실행
findAccounts is executed
Aspect(@AfterReturning) :: afterReturningFindAccountsAdvice is executed after AccountDAO.findAccounts(..)

Main App class :: 
Main App class Accounts List :: [Account [name=Pilseong, level=Admin], Account [name=Suel, level=Admin], Account [name=Noel, level=Staff]]

--------------------------------------------------------------------------------

// 실행 결과 : triggerError = true 경우 - Exception이 발생함
findAccounts is executed
Aspect(@AfterThrowing) :: afterThrowingFindAccountsAdvice is executed after AccountDAO.findAccounts(..)
Main App class :: Exception :: To trigger @AfterThrowing

Main App class :: 
Main App class Accounts List :: null
728x90
댓글