본문 바로가기
👨‍💻 2. 웹개발_Back end/2-6 Spring

[Spring] 4장 JointPoint와 바인드 변수 - 어드바이스 동작 시점 ( Before, After-Returning, After-Throwing, After, Around)에 따라 변하는 매개변수 확인

by 달님🌙 2021. 10. 27.
반응형

 

실습 코드 참조

 

moonhy7/SpringFramework: Spring Framework 실습 코드 정리 (github.com)

 

GitHub - moonhy7/SpringFramework: Spring Framework 실습 코드 정리

Spring Framework 실습 코드 정리. Contribute to moonhy7/SpringFramework development by creating an account on GitHub.

github.com

 

 

4.1절 JoinPoint 메소드

 

1. JoinPoint 메소드를 사용하는 이유

 

- 횡단 관심에 해당되는 어드바이스 메소드를 의미있게 구현하려면 비즈니스 메소드 정보가 필요함

- 예를 들어, After Throwing 기능의 어드바이스 메소드를 구현한다고 가정하면 예외가 발생한 비즈니스 메소드의 이름과 그 메소드가 속한 클래스와 패키지 정보를 알아야함

- 이러한 다양한 정보를 이용할 수 있도록 JoinPoint 인터페이스를 사용

 

 

2. JoinPoint에서 제공하는 유용한 메소드들

 

- ProceedingJoinPoint 인터페이스 : 지금 실행중인 포인트컷 메소드, JoinPoint 인터페이스를 상속받아서 구현한 객체

- ProceedingJoinPoint 인터페이스  : JoinPoint가 가진 모든 메소드를 지원하며 proceed() 메소드를 추가함 

- getTarget() 메소드 예시 : insertBoard 호출 시 BoardServiceImpl 객체 리턴

- Before, After-Returning, After-Throwing, After 어드바이스에서는 JoinPoint를 사용해야 하고 Around 어드바이스에서만 ProceedingJoinPoint를 매개변수로 사용함 (Around 어드바이스에서만 proceed() 메소드가 필요하기 때문)

 

3. 어드바이스별 정리

 

- aop:before, after-returning, after-throwing, after 어드바이스 : JoinPoint 인터페이스를 직접 사용

- aop:around : ProceedingJoinPoint 객체를 사용해야 됨

- ProceedingJoinPoint  : JoinPoint 인터페이스를 상속받아서 추가로 proceed라는 메소드를 구현한 객체

- proceed() : 포인트컷 메소드를 실행하는 메소드

 

4. Signature가 제공하는 메소드들

 

- getSignature() : Signature 객체 리턴 후 Signature 객체에서 사용 가능한 메소드

- getSignature() 메소드가 리턴하는 Signature 객체를 이용하면 호출되는 메소드에 대한 다양한 정보를 얻을 수 있음

- 아래 표는 Signature가 제공하는 메소드들임

 

- JoinPoint는 어드바이스의 종류에 따라 사용방법이 다소 다르다.

-JoinPoint 객체를 사용하려면 JoinPoint를 어드바이스 메소드 매개변수로 선언만 하면 됨

- 그러면 클라이언트가 비즈니스 메소드를 호출할 때 스프링 컨테이너가 JoinPoint 객체를 생성하여 메소드 호출 관련 정보를 JoinPoint 객체에 저장하여 어드바이스 메소드를 호출할 때 인자로 넘겨줌

 

 

4.2절 Before 어드바이스

 

1. Before 어드바이스 ( _034_BoardWeb_AOP_JoinPoint_Before )

 

- JoinPoint 객체의 getSignature() 메소드를 통해 클라이언트가 호출한 메소드 이름을 출력할 수 있음

- 또한 getArgs() 메소드를 통해 인자 목록을 Object 배열로 얻어낼 수있음

package com.springbook.biz.common;

import org.aspectj.lang.JoinPoint;

public class BeforeAdvice {
	public void beforeAdvice(JoinPoint jp) {
		String method = jp.getSignature().getName();
		Object[] args = jp.getArgs();
		
		System.out.println("[사전 처리] " + method + "() 메소드 ARGS 정보 : " + args[0].toString());
	}
}

 

2. 설정 파일

 

<aop:config>
  <aop:pointcut expression="execution(* com.springbook.biz..*Impl.*(..))" id="allPointcut"/>
  <aop:pointcut expression="execution(* com.springbook.biz..*Impl.get*(..))" id="getPointcut"/>

  <aop:aspect ref="before">
    <aop:before pointcut-ref="allPointcut" method="beforeAdvice"/>
  </aop:aspect>
</aop:config>

 

3. 실행 결과

 

- getUser() 메소드가 호출되면서 UserVO 객체가 인자로 전달됨 

-UserVO 객체에 설정된 아이디와 비밀번호 정보도 확인 가능

 

 

4.3절 After Returning 어드바이스

 

1. After Returning 어드바이스 ( _035_BoardWeb_AOP_JoinPoint_AfterReturning )

 

- 첫 번째 매개변수 : 클라이언트가 호출한 비즈니스 메소드 정보를 알아내기 위해 선언

- 두 번째 매개변수 : Object 타입의 변수로서 이를 바인드 변수라고함

- 바인드 변수 : 비즈니스 메소드가 리턴한 결괏값을 바인딩할 목적으로 사용 (어떤 값이 리턴될지 몰라 Object 타입으로 선언)

package com.springbook.biz.common;

import org.aspectj.lang.JoinPoint;
import com.springbook.biz.user.UserVO;

public class AfterReturningAdvice {
	//returnObj : 포인트컷 메소드 실행 후 리턴 값을 받을 객체
	public void afterReturningAdvice(JoinPoint jp, Object returnObj) {
		String method = jp.getSignature().getName();
		if(returnObj instanceof UserVO) {
			UserVO user = (UserVO) returnObj;
			if(user.getRole().equals("Admin")) {
				System.out.println(user.getName() + " 로그인(Admin)");
			}
		}
		
		System.out.println("[사후 처리] " + method + "() 메소드 리턴값 : " + returnObj.toString());
	}
}

 

2. 설정 파일

 

- 바인드 변수가 추가됨에 따라 스프링 설정 파일에서도 바인드 변수에 대한 매핑 설정을 추가해야 한다. (returning 속성 사용)

<aop:config>
  <aop:pointcut expression="execution(* com.springbook.biz..*Impl.*(..))" id="allPointcut"/>
  <aop:pointcut expression="execution(* com.springbook.biz..*Impl.get*(..))" id="getPointcut"/>

  <aop:aspect ref="afterReturning">
    <aop:after-returning pointcut-ref="allPointcut" method="afterReturningAdvice" returnig="returnObj"/>
  </aop:aspect>
</aop:config>

 

3. 실행 결과

 

 

 

4.4절 After Throwing 어드바이스

 

1. 어드바이스 클래스 ( _036_BoardWeb_AOP_JoinPoint_AfterThrowing )

 

- 예외가 발생한 메소드 이름과 발생한 예외 객체의 메시지를 출력하도록 수정

- 예외 객체를 exceptObj라는 바인드 변수를 통해 받는다. (예외 클래스의 최상위 타입인 Exception으로 선언)

package com.springbook.biz.common;

import org.aspectj.lang.JoinPoint;

public class AfterThrowingAdvice {
	public void afterThrowingAdvice(JoinPoint jp, Exception exceptionObj) {
		String method = jp.getSignature().getName();
		
		System.out.println("[예외 처리] " + method + "() 메소드 수행 중 발생한 예외 메시지" + exceptionObj.getMessage());
	}
}

 

2. 설정 파일

 

- 비즈니스 메소드에서 발생한 예외 객체를 exceptObj라는 바인드 변수에 바인드하라는 설정

<aop:config>
  <aop:pointcut expression="execution(* com.springbook.biz..*Impl.*(..))" id="allPointcut"/>
  <aop:pointcut expression="execution(* com.springbook.biz..*Impl.get*(..))" id="getPointcut"/>

  <aop:aspect ref="afterThrowing">
	<aop:after-throwing pointcut-ref="allPointcut" method="afterThrowingAdvice" throwing="exceptionObj"/>
  </aop:aspect>
</aop:config>

 

3. 주석 해제

 

- 예외가 발생해여 AfterThrowing 어드바이스가 동작하므로 주석을 해제해준다.

public void insertBoard(BoardVO vo) {
		//객체 생성 시에 필드 변수의 int 타입들은 0으로 초기화 됨
		if(vo.getSeq() == 0) {
			throw new IllegalArgumentException("0번 글은 등록할 수 없습니다.");
		}
		
		boardDAO.insertBoard(vo);
	}

 

4. 실행 결과

 

 

- 발생하는 예외 객체의 종류에 따라 아래와 같이 다양하게 예외 처리를 할 수도 있다.

 

 

4.5절 생략

 

 

반응형

댓글