실습 코드 참조
moonhy7/SpringFramework: Spring Framework 실습 코드 정리 (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절 생략
댓글