Java의 Dynamic Proxy를 이용한 AOP
모듈화만으로는 중복을 제거하기 힘든 코드들
//시작시간기록
//로깅
//트랜잭선언
try{
//트랜잭션 시작
//핵심업무로직
//커밋
} catch (Exception e){
//트랜잭션 롤백
//로깅 logger.error("...");
//시스템 정의 Exception으로 다시 throw
}
//로깅
//종료시간기록, 수행시간 계산 로깅
위의 코드에서 핵심업무로직을 제외하고는 같은 코드일 경우에도 중복된 코드가 메서드마다 들어가야 하는가
공통적인 실행흐름을 가진 코드의 중복을 제거
- 클로저 (script 언어) (참고자료6)
- Command pattern (참고자료8)
- AOP 활용
대표적인 AOP framework
- Aspect J :
- java 언어를 확장. Aspectj 커맨드라인 컴파일러(ajc)필요
- annotation or XML 으로 aspect 선언
- 가장 오랜 역사 ,풍부한 기능
- 개발을 도와주는 도구로 이클립스 플러그인 ADJT가 있음
- Asjectwertz ;
- java언어를 확장하지 않은 일반 java클래스 사용
- XML로 aspect 선언
- Aspect J 1.5버전에 통합
- Spring AOP
- 기존 java 클래스의 바이트코드를 수정하지 않고 java의 Dynamic proxy이용
- annotation or XML 으로 aspect 선언
- Spring 2.0에서는 Aspect j의 발달한 포인트 컷 언어를 차용
- JBoss AOP
- java의 Dynamic proxy이용. 필요에 따라서 javaAssist를 통해 바이트 코드 조작.
- annotation or XML 으로 aspect 선언
- ejb 프로젝트에서 주로 사용
Ioc(Inversion Of Control)
Inversion Of Control
- 프레임웍 vs라이브러리 (참고자료7)
- 프레임웍 : 프레임웍의 코드가 유저코드를 호출. 실행흐름을 프레임웍이 제어
- 라이브러리 :유저코드가 라이브러리를 호출. 실행흐름을 사용자가 제어
Dynamic proxy를 이용한 간단한 AOP의 구현
참고자료1에서 구한 소스. 첨부파일( proxy.zip )
소스
-
package proxy.sample1;
import java.lang.reflect.Proxy; - import proxy.sample1.ExceptionHandler;
import proxy.sample1.LoggingHandler;
import proxy.sample1.emp.EmpManager;
import proxy.sample1.emp.EmpManagerImpl; - public class ProxyTest
{ - /**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception
{
EmpManager managerProxy = getServerObject(); //서버 객체를 얻어온다.
managerProxy.printGreetingMessage("This is test");
} - /**
* @return
*/
private static EmpManager getServerObject() {
ExceptionHandler exceptionHandler = new ExceptionHandler(new EmpManagerImpl()); - LoggingHandler logHandler = new LoggingHandler(Proxy.newProxyInstance(EmpManager.class.getClassLoader(),
new Class[] { EmpManager.class }, exceptionHandler)); - EmpManager managerProxy = (EmpManager) Proxy.newProxyInstance(EmpManager.class.getClassLoader(),
new Class[] { EmpManager.class }, logHandler);
return managerProxy;
}
}
- package proxy.sample1.emp;
- public interface EmpManager
{
public void printGreetingMessage(String message) throws Exception;
}
- package proxy.sample1.emp;
- public class EmpManagerImpl implements EmpManager
{
public void printGreetingMessage(String message) throws Exception
{
System.out.println( "Hi: " + message); - throw new Exception("일부러 던진 에러 ");
- }
}
- package proxy.sample1;
- import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; - public class ExceptionHandler implements InvocationHandler
{
Object targetObject; - public ExceptionHandler(Object targetObject)
{
this.targetObject = targetObject;
} - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
try
{
return method.invoke(targetObject, args);
}
catch (Throwable e)
{
System.out.println("----------------------------------");
System.out.println("메소드 호출 예외발생:[" + method + "], 에러 메세지[" + e.getMessage() + "]");
System.out.println("----------------------------------");
return null;
}
}
}
- package proxy.sample1;
- import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; - public class LoggingHandler implements InvocationHandler
{
Object targetObject; - public LoggingHandler(Object targetObject)
{
this.targetObject = targetObject;
} - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
try
{
System.out.println("----------------------------------");
System.out.println("메소드 호출 Start:[" + method + "][" + System.currentTimeMillis() + "]");
return method.invoke(targetObject, args);
}
catch (Exception e)
{
throw e;
}
finally
{
System.out.println("메소드 호출 End:[" + method + "][" + System.currentTimeMillis() + "]");
System.out.println("----------------------------------");
}
}
}
실행결과
- 출력내용
----------------------------------
메소드 호출 Start:[public abstract void proxy.sample1.emp.EmpManager.printGreetingMessage(java.lang.String) throws java.lang.Exception][1182822105579]
Hi: This is test
----------------------------------
메소드 호출 예외발생:[public abstract void proxy.sample1.emp.EmpManager.printGreetingMessage(java.lang.String) throws java.lang.Exception], 에러 메세지[null]
----------------------------------
메소드 호출 End:[public abstract void proxy.sample1.emp.EmpManager.printGreetingMessage(java.lang.String) throws java.lang.Exception][1182822105579]
----------------------------------
- EmpManagerImpl 에는 Hi: This is test를 출력하는 코드밖에 없었음에도 앞뒤의 로그와 Exception 처리를 하는 코드가 실행되었음.
CGLib
- Code Generator Library
- 런타임시에 동적으로 클래스의 Proxy를 생성
- CGLib으로 간단히 Proxy 만들기
참고자료
- J2EE(POJO)컴포넌트 만들기 - 부록:AOP를 이용한 트랜잭션 처리 (김형준) (소스 http://blog.naver.com/cookie_00/80023046477 )
- 마이크로소프트웨어 2005/11 테크니컬 컬럼 - 객체지향을 넘어 관점지향으로 AOP (이일민) (http://www.zdnet.co.kr/builder/dev/java/0,39031622,39147106,00.htm )
- 마이크로소프트웨어 2006/09 S/W로 여는 세상 - 관점지향의 개념잡기 -상황중심의 프로그래밍 (임백준) (http://www.zdnet.co.kr/builder/dev/etc/0,39031619,39154322-1,00.htm)
- 3번 자료에 대한 반론 - http://toby.epril.com/?p=229 (이일민님의 블로그)
- 마이크로소프트웨어 2007/03 Cover Story- OOP한계 극복패러다임 AOP (이일민,김백기,박재성, 류대원)
- 마이크로소프트웨어 2007/03 프로그래밍 실전노트 - 클로저(코드 블록)의 개념과 유용성 (서광열)
- 마이크로소프트웨어 2006/11 Coverd story1 -효율적인 프레임워크를 위한 프레임워크의 재발견 (이일민)
- Head First DesignPatterns - 6장 Command Pattern (에릭 프리먼, 일리자베스 프리먼, 케이시 시에라, 버트베이츠)
- 한빛네트워크에 올라온 AOP소개 기사 : http://network.hanb.co.kr/view.php?bi_id=968
History
Last edited on 10/15/2008 18:43 by benelog
Comments (0)