카테고리 없음

[4강] 스프링으로 AOP 구현해보기(Around Advice)

째로스 2023. 6. 16. 11:17

이전 강의에서는 JAVA 코드로 AOP를 구현했었는데, 이번엔 스프링으로 AOP를 구현해보겠다.

 

1. xml 설정

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
						http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd
						http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context">
	
	<!-- 스프링에서는 모든 설정을 setting xml에서 처리함 -->
	<bean id="target" class="spring.aop.entity.NewlecExam" p:kor="1" p:eng="1" p:math="1" p:com="1"/>
	<bean id="logAroundAdvice" class="spring.aop.advice.LogAroundAdvice"/>
	<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
		<!-- 앞의 target은 setTarget을 의미, 뒤 ref의 target은 위의 target빈을 의미 -->
		<!-- 프록시에서 인터페이스는 스프링이 자동으로 처리해주기 때문에 target이랑 핸들러(interceptorNAmes란 이름으로)만 주입해주면된다. -->
		<property name="target" ref="target"/>
		<property name="interceptorNames">
			<list>
				<value>logAroundAdvice</value>
			</list>
		</property>
	</bean>
	
</beans>

스프링에서는 자동으로 인터페이스를 지정해주기 때문에 사용할 객체와 핸들러만 DI 해주면 된다.

여기서 핸들러를 설정할 때, property name으로 interceptorNames를 사용한다.

 

2. 핸들러 클래스 생성

public class LogAroundAdvice implements MethodInterceptor{

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {

		long start=System.currentTimeMillis();
		
		//실제 업무를 담당하는 메소드를 불러옴
		Object result = invocation.proceed();
		
		long end=System.currentTimeMillis();
		
		String message=(end-start)+"ms 시간이 걸렸습니다.";
		
		System.out.println(message);
		
		return result;
	}

}

위 클래스는 스프링에서 사용할 프록시용 핸들러이다.

JAVA 로 AOP를 구현했을 때는 method.invoke(객체,파라미터);를 사용하였지만

스프링에서 핸들러를 구현할 때는 invocation.proceed() 메소드를 사용하여 주 기능을 수행한다.

 

3. 코드 실행

public class NewlecExam implements Exam{
	
    ...
    
	@Override
	public int total() {
		
		int result = kor+eng+math+com;
		
		try {
			Thread.sleep(200);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return result;
	}
	
	@Override
	public float avg() {
		
		float result=total()/4.0f;
		
		try {
			Thread.sleep(200);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return result;
	}
}
public class Program {

	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("spring/aop/setting.xml");
		
		Exam proxy = (Exam) context.getBean("proxy");
		
		System.out.printf("total is %d\n", proxy.total());
		System.out.printf("avg is %f\n", proxy.avg());
	}
}

프록시가 적용되어 NewlecExam의 totla, avg 메소드에서의 주기능뿐만아니라 핸들러의 부가적인 코드들도 수행되었음을 확인할 수 있다.