/*======================
Calculator.java
- 인터페이스
===========================*/
// ※ 스프링에서 AOP 기법을 적용하기 위해서는
// 대상 객체가 인터페이스를 구현하고 있어야 한다.
package com.test.spr;
public interface Calculator
{
//주 업무(core concern) 진행을 위한 메소드 선언
// --- 덧셈 , 뺄셈, 곱셈 나눗셈 연산 수행
public int add(int x,int y);
public int sub(int x,int y);
public int mul(int x,int y);
public int div(int x,int y);
}
package com.test.spr;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.StopWatch;
public class CalculatorImpl implements Calculator
{
// 인터페이스로부터 상속받은 메소드 재정의를 통해
// 주 업무(core concern) 진행(수행)을 위한 메소드 구현
@Override
public int add(int x, int y)
{
// 반환할 결과값
int result = 0;
// 주 엄무(core concern) 실행 내용
result = x + y;
System.out.printf("%d + %d = %d\n", x, y, result);
// 최종 결과값 반환
return result;
}
/*
CalculatorAspect.java
-보조 엄무 수행 클래스.
- 보조 업무 적용 및 주 업무 호출 구조
*/
package com.test.spr;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.StopWatch;
// ※ Spring AOP Proxy 클래스를 설계하기 위해
// MethodInterceptor 인터페이스를 구현하는 클래스로 만든다.
public class CalculatorAspect implements MethodInterceptor
{
//MethodInterceptor 인터페이스의 invoke() 메소드 재정의
@Override
public Object invoke(MethodInvocation method) throws Throwable
{
// 보조 업무 적용 및 주 업무 호출 과정 추가
// 어제 쓴 invoke() 와 크게 다르지 않은데, 매개변수가 다름
// 아래 invoke()에서 매개변수는 InvocationHandler의 invoke() 에서의 method 변수역할 수행함
// 우리가 정의한 메소드 아님 → return 값은 우리가 얻으려는 값이 아님
Object result = null;
//보조 업무(cross-cutting-concern)설정
Log log= LogFactory.getLog(this.getClass());
StopWatch sw = new StopWatch();
sw.start();
log.info("처리시간 측정 시간 ============================");
//주 업무 실행 내용 호출~!
result = method.proceed();
//보조 업무(cross-cutting-concern)처리
sw.stop();
log.info("처리시간 측정 종료=============================");
log.info(String.format("경과시간 : %s/1000초", sw.getTotalTimeMillis()));
return result;
}
}
<!-- ① 먼저 우리가 작성한 클래스 중에 뭘 bean으로 등록할 건지 생각 -->
<!-- CalculatorImpl, CalculatorAspect 객체 생성해야함 -->
<!-- CalculatorImpl 클래스의 객체 생성 및 관리를 위한 정보 전달 -->
<bean id="cal" class="com.test.spr.CalculatorImpl"></bean>
<!-- → 주 업무 수행하는 클래스 -->
<!-- CalculatorAspect 클래스의 객체 생성 및 관리를 위한 정보 전달 -->
<bean id="aspect" class="com.test.spr.CalculatorAspect"></bean>
<!-- → 보조 업무 수행하는 클래스 -->
<!-- check~!!! -->
<!-- 스프링이 제공하는 가짜 객체(Proxy) 클래스의 객체 생성 및 관리를 위한 정보 전달 -->
<!-- → 『ProxyFactoryBean』 → 이름만 기억해두기!
====================
└→ proxyFactory를 찍어내는 bean
+) beanFactory : bean 찍어내는 factory
proxyFactory: proxy 찍어내는 factory -->
<!-- 아무 클래스나 가서 ProxyFactoryBean 입력했다가 지우면, import 구문 작성됨
그 import 구문 복사해서 class="" 에 작성함 -->
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- └→ 너가 가진 설계도 사용해서 proxy 만들어줘 -->
<!-- 주 업무 클래스의 인터페이스 정보 제공 -->
<!-- → 『proxyInterfaces』 -->
<!-- 단일값 넘겨주는 애가 아니니까 → list로 구성 -->
<!-- 그런데 여기서 넘기는건 사실상 한 개 넘김 (여러개일 때는 쭉 나열하면 됨)-->
<property name="proxyInterfaces">
<list>
<value>com.test.spr.Calculator</value>
</list>
</property>
<!-- 주 업무 클래스의 객체 정보 제공 -->
<!-- → 『target』 -->
<!-- 주업무 수행해야 하는 거 → CalculatorImpl
→ 단수로 제공되는거니까 그냥 ref="cal" 참조하라고 하면 끝!
그런데 다른 복수로 제공되는 것들은 list 만들어서 넘겨줘야 한다. -->
<property name="target" ref="cal"></property>
<!-- 보조 업무 클래스의 객체 정보 제공 -->
<!-- → 『interceptorNames』 -->
<!-- 보조 업무도 before/after/aroundAdvice 여러개가 있을 수 있으니 복수형으로 names! -->
<!-- 그런데 여기서 넘기는건 사실상 한 개 넘김 -->
<property name="interceptorNames">
<list>
<!-- 보조 업무는 우리가 위에서 aspect로 만들어놓았음 -->
<value>aspect</value>
</list>
</property>
</bean>
<!--
proxy 쓸 때, property name으로
proxyInterfaces, target, interceptorNames 는 고정!
proxy가 그 값들을 필요로 함
-->
즉 이전에 개발자가 Main 에서 사용하던 proxy.newproxyInstance(); 가 하던일을 설정 정보로써 넘겨 Spring이 자체적으로 객체를 관리하게 만드는것
//주 업무 실행에 대한 테스트(Spring AOP 기법 적용 후)
ApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
//Spring 에서 제공하는 proxy를 활용하여
//보조 업무와 결합된 형태로 업무 처리~~!!!
//인터페이스 형태의 변수명에 = new 인터페이스를 구현한 객체();
Calculator cal = context.getBean("proxy", Calculator.class);
int add = cal.add(10, 20);
System.out.println(add);