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

Spring/Spring Quick Start

Annotation ๊ธฐ๋ฐ˜ AOP ์ ์šฉ

<aop:aspectj-autoproxy>

AOP๋ฅผ ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ์„ค์ •ํ•˜๋ ค๋ฉด, ๊ฐ€์žฅ ๋จผ์ € ์Šคํ”„๋ง ์„ค์ • ํŒŒ์ผ์— <aop:aspectj-autoproxy> ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์„ ์–ธํ•ด์•ผ ํ•œ๋‹ค. ์ด๊ฒƒ๋งŒ ์„ค์ •ํ•˜๋ฉด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” AOP ๊ด€๋ จ ์–ด๋…ธํ…Œ์ด์…˜๋“ค์„ ์ธ์‹ํ•˜๊ณ  ์šฉ๋„์— ๋งž๊ฒŒ ์ฒ˜๋ฆฌํ•ด์ค€๋‹ค.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">

	<context:component-scan base-package="com.springbook.biz" />		
	
	 <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

@Pointcut

package com.springbook.biz.common;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class PointcutCommon {
	@Pointcut("execution(* com.springbook.biz..*Impl.*(..))")
	public void allPointcut() {
	}

	@Pointcut("execution(* com.springbook.biz..*Impl.get*(..))")
	public void getPointcut() {
	}
}

ํฌ์ธํŠธ์ปท์„ ์„ ์–ธํ•˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ด๋‹ค. 
์—ฌ๋Ÿฌ ๊ฐœ์˜ ํฌ์ธํŠธ์ปท์„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์—ฌ๋Ÿฌ ํฌ์ธํŠธ์ปท์„ ์‹๋ณ„ํ•˜๊ธฐ ์œ„ํ•ด ์ฐธ์กฐ ๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•œ๋‹ค.
์ฐธ์กฐ ๋ฉ”์†Œ๋“œ๋Š” ๊ตฌํ˜„ ๋กœ์ง์ด ์—†๋Š” ๋ฉ”์†Œ๋“œ์ด๋‹ค. 
์–ด๋–ค ๊ธฐ๋Šฅ์ฒ˜๋ฆฌ๋ฅผ ๋ชฉ์ ์œผ๋กœ ํ•˜์ง€ ์•Š๊ณ  ๋‹จ์ˆœํžˆ ํฌ์ธํŠธ์ปท์„ ์‹๋ณ„ํ•˜๋Š” ์ด๋ฆ„์œผ๋กœ๋งŒ ์‚ฌ์šฉ๋œ๋‹ค.

ํฌ์ธํŠธ์ปท์„ ์™ธ๋ถ€์— ๋…๋ฆฝ๋œ ํด๋ž˜์Šค์— ๋”ฐ๋กœ ์„ค์ •ํ•˜์—ฌ ๋ฐ˜๋ณต ์„ ์–ธํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

์–ด๋“œ๋ฐ”์ด์Šค์—์„œ ํฌ์ธํŠธ์ปท์„ ์ฐธ์กฐํ•˜๋ ค๋ฉด "PointcutCommon.allPointcut()"์™€ ๊ฐ™์ด ํด๋ž˜์Šค์ด๋ฆ„๊ณผ ์ฐธ์กฐ ๋ฉ”์†Œ๋“œ ์ด๋ฆ„ ์“ฐ๋ฉด ๋œ๋‹ค. 

@Service

์–ด๋“œ๋ฐ”์ด์Šค ํด๋ž˜์Šค๋Š” ๋ฐ˜๋“œ์‹œ @Service ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ฒ€์ƒ‰๋  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์•ผ ํ•œ๋‹ค.

@Aspect

Aspect๋Š” Pointcut๊ณผ Advice์˜ ๊ฒฐํ•ฉ์ด๋‹ค.

๋”ฐ๋ผ์„œ @Aspect๊ฐ€ ์„ค์ •๋œ ์• ์ŠคํŒฉํŠธ ๊ฐ์ฒด์—๋Š” ๋ฐ˜๋“œ์‹œ ํฌ์ธํŠธ์ปท๊ณผ ์–ด๋“œ๋ฐ”์ด์Šค๋ฅผ ๊ฒฐํ•ฉํ•˜๋Š” ์„ค์ •์ด ์žˆ์–ด์•ผ ํ•œ๋‹ค.

์–ด๋“œ๋ฐ”์ด์Šค ์„ค์ •

@Before

allPointCut()์œผ๋กœ ์ง€์ •ํ•œ ๋ฉ”์†Œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ, beforeLog() ๋ฉ”์†Œ๋“œ๊ฐ€ Before ํ˜•ํƒœ๋กœ ๋™์ž‘ํ•˜๋„๋ก ์„ค์ •ํ–ˆ๋‹ค.

package com.springbook.biz.common;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Service;

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

@AfterReturning

After Returning ์–ด๋“œ๋ฐ”์ด์Šค๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋ฉ”์†Œ๋“œ ์ˆ˜ํ–‰ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์•„๋‚ด๊ธฐ ์œ„ํ•ด ๋ฐ”์ธ๋“œ ๋ณ€์ˆ˜๋ฅผ ์ง€์ •ํ•œ๋‹ค.

@AfterReturning์˜ returning ์†์„ฑ์„ ์ด์šฉํ•˜์—ฌ ๋ฐ”์ธ๋“œ ๋ณ€์ˆ˜๋ฅผ ์ง€์ •ํ•˜๊ณ  ์žˆ๋‹ค.

package com.springbook.biz.common;

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

import com.springbook.biz.user.UserVO;

@Service
@Aspect
public class AfterReturningAdvice {
	@AfterReturning(pointcut="PointcutCommon.getPointcut()", returning="returnObj")
	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());
	}
}

@AfterThrowing

@AfterThrowing๋Š” throwing ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ”์ธ๋“œ ๋ณ€์ˆ˜๋ฅผ ์ง€์ •ํ•˜๊ณ  ์žˆ๋‹ค.

package com.springbook.biz.common;

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

@Service
@Aspect
public class AfterThrowingAdvice {
	
	@AfterThrowing(pointcut="PointcutCommon.allPointcut()", throwing="exceptObj")
	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("๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.");
		}
	}
}

@After

package com.springbook.biz.common;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Service;

@Service
@Aspect
public class AfterAdvice {
	@After("PointcutCommon.allPointcut()")
	public void finallyLog() {
		System.out.println("[์‚ฌํ›„ ์ฒ˜๋ฆฌ] ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ˆ˜ํ–‰ ํ›„ ๋ฌด์กฐ๊ฑด ๋™์ž‘");
	}
}

@Around

Around ์–ด๋“œ๋ฐ”์ด์Šค๋งŒ ProceedingJoinPoint ๊ฐ์ฒด๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์•„ proceed() ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

package com.springbook.biz.common;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;

@Service
@Aspect
public class AroundAdvice {
	@Around("PointcutCommon.allPointcut()")
	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;
	}
}