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

[Spring] 3장 어드바이스 동작 시점 ( 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

 

 

3.0절 어드바이스 동작 시점

 

- 어드바이스는 각 조인포인트에 삽입되어 동작할 횡단 관심에 해당하는 공통 기능

- 동작 시점은 각 AOP 기술마다 다름, 스프링에서는 5가지 동작 시점을 제공

 

- 어드바이스 메소드의 동작 시점은 <aop:aspect> 엘리먼트 하위에 각각의 엘리먼트를 이용하여 지정함

 

3.1절 Before 어드바이스 

 

1. Before 어드바이스 구조

- before 어드바이스는 포인트컷으로 지정된 메소드 호출 시 메소드가 실행되기 전에 처리될 내용들을 기술하는데 사용

 

2. Before 어드바이스 실습 ( _029_BoardWeb_AOP_Before )

 

1) Before 어드바이스 클래스

- 비즈니스 메소드가 실행되기 전에 수행될 기능을 담은 beforeAdvice() 메소드 선언

package com.springbook.biz.common;

public class BeforeAdvice {
	public void beforeAdvice() {
		System.out.println("[사전 처리] 비즈니스 로직 수행 전 동작");
	}
}

 

 

2) 스프링 설정 파일

- <aop:before> 엘리먼트를 사용함

- allPointcut으로 지정한 모든 Impl 클래스의 메소드가 실행되기 직전에 before로 지정한 어드바이스의 beforeAdvice() 메소드가 실행되도록 설정함

<bean id="before" class="com.springbook.biz.common.BeforeAdvice"></bean>

<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) 실행 결과

- before 형태로 메소드가 동작하는 것을 알 수 있음

 

 

3.2절 After Returning 어드바이스

 

1. After Returning 어드바이스 구조

- After Returning 어드바이스는 포인트컷으로 지정된 메소드가 정상적으로 실행되고 나서 메소드 수행 결과로 생성된 데이터를 리턴하는 시점에 동작함

- 비즈니스 메소드 수행 결과로 얻은 결과 데이터를 이용하여 사후 처리 로직을 추가할 때 사용

 

2. After Returning 어드바이스 실습 ( _030_BoardWeb_AOP_AfterReturning ) 

 

1) After Returning 어드바이스 클래스

package com.springbook.biz.common;

public class AfterReturningAdvice {
	public void afterReturningAdvice() {
		System.out.println("[사후 처리] 비즈니스 로직 수행 후 동작");
	}
}

 

2) 스프링 설정 파일

- <aop:afterReturning> 엘리먼트를 사용함

- Impl로 끝나는 모든 메소드가 실행되기 이후에 afterReturning로 지정한 afterReturningAdvice() 메소드가 실행되도록 설정함

<bean id="afterReturning" class="com.springbook.biz.common.AfterReturningAdvice"></bean>
<aop:aspect ref="afterReturning">
<!-- 어드바이스 동작 시점 : aop:before, aop:after, aop:arround...
    aop:before : 포인트컷 메소드가 실행되기 전에 동작
    aop:after-returning : 포인트컷 메소드가 정상적으로 리턴되면 동작(try에 해당)
    aop:after-throwing : 포인트컷 메소드 실행중에 예외가 발생하면 동작(catch에 해당)
    aop:after : 포인트컷 메소드가 완료된후 무조건 실행(finally에 해당) 
    aop:arround : 포인트컷 메소드 호출을 가로채서 포인트컷 실행 전후에 처리할 어드바이스 삽입-->
<aop:after-returning pointcut-ref="getPointcut" method="afterReturningAdvice"/>

 

3) 실행 결과

 

 

3.3절 After Throwing 어드바이스

 

1. After Throwing 어드바이스 구조

- After Throwing 어드바이스는 포인트컷으로 지정한 메소드가 실행되다가 예외가 발생하는 시점에 동작함

- 따라서 예외 처리 어드바이스를 설정할 때 사용

 

2. After Throwing 어드바이스 테스트 ( _031_BoardWeb_AOP_AfterThrowing )

 

1) 어드바이스 클래스 구현

- 예외 처리 기능을 가진 어드바이스 클래스

package com.springbook.biz.common;

public class AfterThrowingAdvice {
	public void afterThrowingAdvice() {
		System.out.println("[예외 처리] 비즈니스 로직 처리 중 예외 발생");
	}
}

 

2) 스프링 설정 추가 

- 예외 발생 시, 예외 처리 어드바이스가 동작할 수 있도록 스프링 설정 추가

- afterThrowing 어드바이스의 exceptionLog() 메소드를 실행하기 위해 allPointcut으로 포인트컷 지정

<bean id="afterThrowing" class="com.springbook.biz.common.AfterThrowingAdvice"></bean>
<aop:aspect ref="afterThrowing">
	<aop:after-throwing pointcut-ref="allPointcut" method="afterThrowingAdvice"/>
</aop:aspect>

 

3) 예외 코드 추가

- After Throwing 어드바이스는 비즈니스 메소드에서 예외가 발생할 때만 동작하므로 예외 코드 추가

- 글 등록 작업에서 서브쿼리를 사용하여 SEQ 컬럼값을 자동으로 증가시켜서 0부터 시작이된다.

- 예외 처리 테스트를 위해서 seq 변수값이 0이면 IllegalArgumentException을 강제로 발생시킴

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

 

4) 실행 결과

- afterThrowingAdvice() 메소드 수행됨

 

3.4절 After 어드바이스

 

1. After 어드바이스 구조

- try-catch-finally 구문에서 finally 블록처럼 예외 발생 여부에 상관없이 무조건 수행되는 어드바이스를 등록할 때 After 어드바이스를 사용

 

2. After 어드바이스 테스트 ( _032_BoardWeb_AOP_After )

 

1) 어드바이스 클래스 구현

- 예외 처리 기능의 어드바이스 클래스 구현

package com.springbook.biz.common;

public class AfterAdvice {
	public void afterAdvice() {
		System.out.println("[사후 처리] 비즈니스 로직 수행 후 무조건 동작");
	}
}

 

2) 스프링 설정에 따른 각 실행 결과

- 예외가 발생한 상황에서도 afterAdvice() 메소드가 먼저 실행되고 afterThrowingAdvice() 메소드가 그 다음에 실행됨

<bean id="afterThrowing" class="com.springbook.biz.common.AfterThrowingAdvice"></bean>
<bean id="after" class="com.springbook.biz.common.AfterAdvice"></bean>
<aop:config>
	<aop:aspect ref="afterThrowing">
		<aop:after-throwing pointcut-ref="allPointcut" method="afterThrowingAdvice"/>
	</aop:aspect>
		
	<aop:aspect ref="after">
		<aop:after pointcut="allpointcut" method="afterAdvice"/>
	</aop:aspect>
</aop:config>

 

- 예외가 발생하지 않을 땐 각 비즈니스 메소드 실행 후 afterAdvice() 메소드가 실행됨

<bean id="afterThrowing" class="com.springbook.biz.common.AfterThrowingAdvice"></bean>
<bean id="after" class="com.springbook.biz.common.AfterAdvice"></bean>
<aop:config>
	<aop:aspect ref="afterReturning">
		<aop:after-returning pointcut-ref="allPointcut" method="afterReturningAdvice"/>
	</aop:aspect>
		
	<aop:aspect ref="after">
		<aop:after pointcut="allpointcut" method="afterAdvice"/>
	</aop:aspect>
</aop:config>

 

 

3.5절 Around 어드바이스

 

- 하나의 어드바이스가 비즈니스 메소드 실행 전과 후에 모두 동작하여 로직을 처리하는 경우 Around 어드바이스 사용

 

1. Around 어드바이스 구조

- Around 어드바이스는 하나의 어드바이스가 비즈니스 메소드 실행 전과 후에 모두 동작하여 로직을 처리하는 경우에 사용

 

2. Around 어드바이스 테스트 ( _033_BoardWeb_AOP_Around )

 

1) 어드바이스 클래스 구현

- Around 어드바이스는 클라이언트의 메소드 호출을 가로챈다.

- 따라서 클라이언트가 호출한 비즈니스 메소드가 실행되기 전에 사전 처리 로직을 수행 (php.proceed() 메소드 호출 앞에 작성된 코드는 Before 어드바이스와 동일하게 동작) 

- 비즈니스 메소드가 모두 실행되고 나서 사후 처리 로직을 수행할 수 있음 (php.proceed() 메소드 호출 뒤에 작성된 코드는 After 어드바이스와 동일하게 동작)

- ProceedingJoinPoint 객체를 매개변수로 받아 proceed() 메소드를 통해서 비즈니스 메소드를 호출함

package com.springbook.biz.common;

import org.aspectj.lang.ProceedingJoinPoint;

public class AroundAdvice {
	//ProceedingJoinPoint : 지금 실행중인 포인트컷 메소드, JoinPoint 인터페이스를 상속받아서 구현한 객체
	public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("[BEFORE] : 비즈니스 로직 수행 전 처리할 내용...");
		Object returnObj = pjp.proceed();
		System.out.println("[AFTER] : 비즈니스 로직 수행 후 처리할 내용...");
		return returnObj;
	}
}

 

 

2) 스프링 설정 추가 

<bean id="afterThrowing" class="com.springbook.biz.common.AfterThrowingAdvice"></bean>
<bean id="around" class="com.springbook.biz.common.AroundAdvice"></bean>
<aop:config>
	<aop:aspect ref="around">
		<aop:around pointcut-ref="allPointcut" method="aroundAdvice"/>
	</aop:aspect>
</aop:config>

 

3) 실행 결과

 

 

반응형

댓글