๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Spring/Spring Quick Start

JointPoint ๋ฉ”์†Œ๋“œ

JointPoint ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด JointPoint๋ฅผ ์–ด๋“œ๋ฐ”์ด์Šค ๋ฉ”์†Œ๋“œ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์„ ์–ธ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค.

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์ž๋™์œผ๋กœ JointPoint ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ๊ณผ ๊ด€๋ จ๋œ ๋ชจ๋“  ์ •๋ณด๋ฅผ JointPoint ๊ฐ์ฒด์— ์ €์žฅํ•˜์—ฌ ์–ด๋“œ๋ฐ”์ด์Šค ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์ธ์ž๋กœ ๋„˜๊ฒจ์ค€๋‹ค.

1. Before ์–ด๋“œ๋ฐ”์ด์Šค

ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋น„์ฆˆ๋‹ˆ์Šค ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ, ์ธ์ž๋กœ ๋„˜๊ฒจ์ค€ ๊ฐ’๋“ค์„ JoinPoint๋ฅผ ์ด์šฉํ•˜์—ฌ ์ถœ๋ ฅํ•˜๋„๋ก ์ž‘์„ฑํ–ˆ๋‹ค.

JoinPoint ๊ฐ์ฒด์˜ getSignature() ๋ฉ”์†Œ๋“œ๊ฐ€ ๋ฆฌํ„ดํ•˜๋Š” Signature ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•˜๋ฉด, ํ˜ธ์ถœ๋˜๋Š” ๋ฉ”์†Œ๋“œ์— ๋Œ€ํ•œ ๋‹ค์–‘ํ•œ ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค. getName(), getLongString() ๋“ฑ์ด ์žˆ๋‹ค. getArgs() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด์„œ๋Š” ์ธ์ž ๋ชฉ๋ก์„ Object ๋ฐฐ์—ด๋กœ ์–ป์–ด๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

package com.springbook.biz.common;

import org.aspectj.lang.JoinPoint;

public class BeforeAdvice {
	public void beforeLog(JoinPoint jp){
		String method = jp.getSignature().getName();
		Object[] args = jp.getArgs();
		
		System.out.println("[์‚ฌ์ „ ์ฒ˜๋ฆฌ] " + method + "() ๋ฉ”์†Œ๋“œ ARGS ์ •๋ณด : " + args[0].toString());
	}
}

2. After Returning ์–ด๋“œ๋ฐ”์ด์Šค

Object ํƒ€์ž…์˜ ๋ณ€์ˆ˜๊ฐ€ ๋‘ ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์„ ์–ธ๋˜์–ด ์žˆ๋Š”๋ฐ, '๋ฐ”์ธ๋“œ ๋ณ€์ˆ˜'๋ผ๊ณ  ํ•œ๋‹ค.๋ฐ”์ธ๋“œ ๋ณ€์ˆ˜๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋ฉ”์†Œ๋“œ๊ฐ€ ๋ฆฌํ„ดํ•œ ๊ฒฐ๊ด๊ฐ’์„ ๋ฐ”์ธ๋”ฉํ•  ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

package com.springbook.biz.common;

import org.aspectj.lang.JoinPoint;

import com.springbook.biz.user.UserVO;

public class AfterReturningAdvice {
	public void afterLog(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());
	}
}

๋ฐ”์ธ๋“œ ๋ณ€์ˆ˜๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ๋‹ค๋ฉด ๋ฐ˜๋“œ์‹œ ๋ฐ”์ธ๋“œ ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ๋งคํ•‘ ์„ค์ •์„ ์Šคํ”„๋ง ์„ค์ • ํŒŒ์ผ(applicationContext.xml)์— ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค. ๋ฐ”์ธ๋“œ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด <aop:after-returning> ์—˜๋ฆฌ๋จผํŠธ์˜ returing ์†์„ฑ์„ ์ด์šฉํ•œ๋‹ค.

<aop:after-returning pointcut-ref="getPointcut" method="afterLog" throwing="returnObj"/>

3. After Throwing ์–ด๋“œ๋ฐ”์ด์Šค

์ด๋ฒˆ์—๋Š” ๋‘ ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜์— ์˜ˆ์™ธ ํด๋ž˜์Šค์˜ ์ตœ์ƒ์œ„ ํƒ€์ž…์ธ Exception์„ ์„ ์–ธํ•˜์—ฌ exceptObj ๋ฐ”์ธ๋“œ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

package com.springbook.biz.common;

import org.aspectj.lang.JoinPoint;

public class AfterThrowingAdvice {
	public void exceptionLog(JoinPoint jp, Exception exceptObj) {
		String method = jp.getSignature().getName();
//		System.out.println("[์˜ˆ์™ธ ์ฒ˜๋ฆฌ] " + method + "() ๋ฉ”์†Œ๋“œ ์ˆ˜ํ–‰ ์ค‘ ๋ฐœ์ƒ๋œ ์˜ˆ์™ธ ๋ฉ”์‹œ์ง€ : " + exceptObj.getMessage());

		System.out.println(method + "() ๋ฉ”์†Œ๋“œ ์ˆ˜ํ–‰ ์ค‘ ์˜ˆ์™ธ ๋ฐœ์ƒ!");
		if (exceptObj instanceof IllegalArgumentException) {
			System.out.println("๋ถ€์ ํ•ฉํ•œ ๊ฐ’์ด ์ž…๋ ฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.");
		} else if (exceptObj instanceof NumberFormatException) {
			System.out.println("์ˆซ์ž ํ˜•์‹์˜ ๊ฐ’์ด ์•„๋‹™๋‹ˆ๋‹ค.");
		} else if (exceptObj instanceof Exception) {
			System.out.println("๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.");
		}
	}
}

๋ฐ”์ธ๋“œ ๋ณ€์ˆ˜๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ๋‹ค๋ฉด ๋ฐ˜๋“œ์‹œ ๋ฐ”์ธ๋“œ ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ๋งคํ•‘ ์„ค์ •์„ ์Šคํ”„๋ง ์„ค์ • ํŒŒ์ผ(applicationContext.xml)์— ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค. ์ด ๋•Œ throwing ์†์„ฑ์„ ์ด์šฉํ•œ๋‹ค.

<aop:after-throwing pointcut-ref="allPointcut" method="exceptionLog" throwing="exceptObj"/>

4. Around ์–ด๋“œ๋ฐ”์ด์Šค

Around ์–ด๋“œ๋ฐ”์ด์Šค๋Š” ๋‹ค๋ฅธ ์–ด๋“œ๋ฐ”์ด์Šค์™€ ๋‹ค๋ฅด๊ฒŒ ๋ฐ˜๋“œ์‹œ ProceedingJoinPoint ๊ฐ์ฒด๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์•„์•ผ ํ•œ๋‹ค.

Around ์–ด๋“œ๋ฐ”์ด์Šค์—์„œ๋งŒ proceed() ๋ฉ”์†Œ๋“œ๊ฐ€ ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

ProceedingJoinPoint ๊ฐ์ฒด๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” proceed() ๋ฉ”์†Œ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ JoinPoint๋ฅผ ์ƒ์†ํ•œ๋‹ค.

package com.springbook.biz.common;

import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.util.StopWatch;

public class AroundAdvice {
	public Object aroundLog(ProceedingJoinPoint pjp) throws Throwable {
		String method = pjp.getSignature().getName();
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		Object obj = pjp.proceed();
		stopWatch.stop();
		System.out.println(method + "() ๋ฉ”์†Œ๋“œ ์ˆ˜ํ–‰์— ๊ฑธ๋ฆฐ ์‹œ๊ฐ„ : " + stopWatch.getTotalTimeMillis() + "(ms)์ดˆ");
		return obj;
	}
}