Java의 Dynamic Proxy를 이용한 AOP

 

모듈화만으로는 중복을 제거하기 힘든 코드들

//시작시간기록

//로깅

//트랜잭선언

try{

//트랜잭션 시작

//핵심업무로직

//커밋

} catch (Exception e){

//트랜잭션 롤백

//로깅 logger.error("...");

//시스템 정의 Exception으로 다시 throw

}

//로깅

//종료시간기록, 수행시간 계산 로깅

 

위의 코드에서 핵심업무로직을 제외하고는 같은 코드일 경우에도 중복된 코드가 메서드마다 들어가야 하는가

 

 

공통적인 실행흐름을 가진 코드의 중복을 제거

 

 

대표적인 AOP framework

 

 

 

 

 

Ioc(Inversion Of Control)

Inversion Of Control

 

Dynamic proxy를 이용한 간단한 AOP의 구현

참고자료1에서 구한 소스. 첨부파일( proxy.zip )

소스

 

  1. package proxy.sample1;

    import java.lang.reflect.Proxy;
  2. import proxy.sample1.ExceptionHandler;
    import proxy.sample1.LoggingHandler;
    import proxy.sample1.emp.EmpManager;
    import proxy.sample1.emp.EmpManagerImpl;
  3. public class ProxyTest
    {
  4.     /**
         * @param args
         * @throws Exception
         */
        public static void main(String[] args) throws Exception
        {
            EmpManager managerProxy = getServerObject(); //서버 객체를 얻어온다.
            managerProxy.printGreetingMessage("This is test");
        }
  5.     /**
         * @return
         */
        private static EmpManager getServerObject() {
            ExceptionHandler exceptionHandler = new ExceptionHandler(new EmpManagerImpl());
  6.         LoggingHandler logHandler = new LoggingHandler(Proxy.newProxyInstance(EmpManager.class.getClassLoader(),
                    new Class[] { EmpManager.class }, exceptionHandler));
  7.         EmpManager managerProxy = (EmpManager) Proxy.newProxyInstance(EmpManager.class.getClassLoader(),
                    new Class[] { EmpManager.class }, logHandler);
            return managerProxy;
        }
    }

 

  1. package proxy.sample1.emp;
  2. public interface EmpManager
    {
        public void printGreetingMessage(String message) throws Exception;
    }

 

  1.  
  2. package proxy.sample1.emp;
  3. public class EmpManagerImpl implements EmpManager
    {
        public void printGreetingMessage(String message) throws Exception
        {
            System.out.println( "Hi: " + message);
  4.         throw new Exception("일부러 던진 에러 ");
  5.     }
    }

 

 

  1. package proxy.sample1;
  2. import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
  3. public class ExceptionHandler implements InvocationHandler
    {
        Object targetObject;
  4.     public ExceptionHandler(Object targetObject)
        {
            this.targetObject = targetObject;
        }
  5.     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;
            }
        }
    }

 

  1. package proxy.sample1;
  2. import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
  3. public class LoggingHandler implements InvocationHandler
    {
        Object targetObject;
  4.     public LoggingHandler(Object targetObject)
        {
            this.targetObject = targetObject;
        }
  5.     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]
----------------------------------

 

 

CGLib

 

 

참고자료

  1. J2EE(POJO)컴포넌트 만들기 - 부록:AOP를 이용한 트랜잭션 처리 (김형준) (소스 http://blog.naver.com/cookie_00/80023046477 )
  2. 마이크로소프트웨어 2005/11 테크니컬 컬럼 - 객체지향을 넘어 관점지향으로 AOP (이일민)   (http://www.zdnet.co.kr/builder/dev/java/0,39031622,39147106,00.htm )
  3. 마이크로소프트웨어 2006/09 S/W로 여는 세상 - 관점지향의 개념잡기 -상황중심의 프로그래밍 (임백준) (http://www.zdnet.co.kr/builder/dev/etc/0,39031619,39154322-1,00.htm)
  4. 3번 자료에 대한 반론 - http://toby.epril.com/?p=229 (이일민님의 블로그)
  5. 마이크로소프트웨어 2007/03 Cover Story- OOP한계 극복패러다임 AOP (이일민,김백기,박재성, 류대원)
  6. 마이크로소프트웨어 2007/03 프로그래밍 실전노트 - 클로저(코드 블록)의 개념과 유용성 (서광열)
  7. 마이크로소프트웨어 2006/11 Coverd story1 -효율적인 프레임워크를 위한 프레임워크의 재발견 (이일민)
  8. Head First DesignPatterns - 6장 Command Pattern (에릭 프리먼, 일리자베스 프리먼, 케이시 시에라, 버트베이츠)
  9. 한빛네트워크에 올라온 AOP소개 기사 : http://network.hanb.co.kr/view.php?bi_id=968