파게로그

Spring으로 AOP 구현 본문

콤퓨타 왕기초/Spring

Spring으로 AOP 구현

파게 2021. 4. 22. 00:14

Spring으로 AOP 구현

XML이든 annotation이든, 공통 기능이 가시적이지 않다. 여기서는 먼저 XML을 통해서 AOP를 구현해보자. Program.java는 다음과 같아서 마치 비즈니스 로직만 존재하는 것처럼 보인다.

 

Program.java

package spring.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import spring.aop.entity.Exam;

public class Program {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/aop/setting.xml");

        Exam exam = (Exam)ctx.getBean("exam");
        System.out.printf("SUM: %d\n", exam.sum());
        System.out.printf("AVG: %.2f\n", exam.avg());
    }
}

 

하지만 위 코드에서 examExam 클래스의 인스턴스가 아니라, 엄밀히는 Proxy 객체이다. 그래서 실제로 비즈니스 로직은 공통 기능의 앞이나 뒤에 있거나 둘러싸여 있는 것이다.

 

setting.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">

    <bean id="target" class="spring.aop.entity.MidTermExam">
    	<property name="kor" value="90" />
    	<property name="eng" value="100" />
    	<property name="math" value="70" />
    	<property name="com" value="80" />
    </bean>
    
    <bean id="logAroundAdvice" class="spring.aop.advice.LogAroundAdvice" />
    
    <bean id="exam" class="org.springframework.aop.framework.ProxyFactoryBean">
		<!-- target class -->
		<property name="target" ref="target"/>
		
		<!-- invocation handler -->
		<property name="interceptorNames">
			<list>
				<value>logAroundAdvice</value>
			</list>
		</property>
    </bean>

</beans>

 

'exam'이라는 이름으로 ProxyFactoryBean 객체를 생성한다. 두 개의 필드를 setter를 통해 설정하는데, 첫번째는 target으로서 둘러싸일(?) 비즈니스 로직을 가진 클래스의 Bean 객체이고, 두번째는 그것을 둘러싼 공통 기능의 모듈인 Advice 목록이다.

여기서 logAroundAdvice 또한 Bean 객체가 생성되어 있어야 하는데, 그 본래 클래스는 다음과 같다.

 

LogAroundAdvice.java

package spring.aop.advice;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

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();
		long duration = end - start;
		System.out.println(duration + "ms elapsed.");
		
		return result;
	}
}

 

Program.java를 실행하면 다음과 같은 결과를 성공적으로 얻을 수 있다.

 

0ms elapsed.
SUM: 340
0ms elapsed.
AVG: 85.00
Comments