DNA 포럼 API 서비스 모음 DNA Lens

AOP 용어들과 DynamicProxy를 사용한 간단한 예제


  • 구준근(기술위원회 PiLab팀), 2006년 11월

초록(Abstract) AOP에서 사용되는 용어들과 JDK DynamicProxy를 이용한 예제작성

서론 #

  • AOP에서 사용되는 용어들을 이해하고 JDK DynamicProxy를 이용하여 간단히 예제를 만들어 본다.

본론 #

  • AOP에서 새롭게 등장한 용어
http://dna.daum.net/wiki/imgs/custom/aop.jpg

  • Target : 주가 되는 비지니스 로직을 구현하고 있는 클래스를 말합니다.

  • JointPoint : Target 즉, 주가 되는 비지니스 로직을 가지는 인스턴스에 이벤트가 발생하는 시점을 말합니다.
    예를 들면 인스턴스가 생성되거나, 인스턴스의 특정 메소드가 호출되는 시점 또는 Exception이 발생하는 시점 등이 예가 됩니다.

  • Advice : target의 주된 비지니스 로직에 추가로 실행되어질 로직이 구현된 부분 입니다.

  • PointCut : Target의 JointPoint에 Advice를 결합하기 위해서 필요한 패턴을 말합니다.

  • Weaving : Target에 Advice 기능을 결합시키는 것을 말합니다. JAVA JDK에서는 1.3 버전부터 reflect API를 사용한
    DynamicProxy 클래스를 지원하여 부분적인 AOP를 구현하고 있으며, AspectJ 등의 툴은 바이너리 파일을 재 컴파일하여 AOP를 완벽히 지원하고 있습니다.

  • Aspect : Target의 JointPoint에 Advice 기능이 Weaving 되어 Target에 주된 비지니스 로직에 Advice 기능을 지원할 수 있도록 하는 완성된 클래스 입니다.

  • DynamicProxy를 통한 예제
    • DynamicProxy를 통한 AOP 맛보기 JDK에 포함된 DynamicProxy를 통해서 간단한 AOP를 구현해 보겠습니다.
    • Orc라는 인터페이스와 이를 구현한 OrcImpl이 있습니다. Orc가 가지는 주된 비지니스 로직은 다음과 같습니다.
    • orc에게는 인사를 하는 sayHell() 메소드와 이동하는 orcGo()라는 메소드가 있습니다.
    • 특히 orcGo() 메소드는 방향을 뜻하는 parameter가 필요합니다. 방향은 동,서,남,북 이렇게 4가지 이며, 실행시키면 다음과 같은 메세지를 찍습니다.

Orc.java
public interface Orc
{
	public final static int __DIRECTION_NORTH = 1;
	public final static int __DIRECTION_SOUTH = 2;
	public final static int __DIRECTION_EAST = 3;
	public final static int __DIRECTION_WEST = 4;
	
	public void sayHello(String name);
	public void orcGo(int direction);
}

OrcImpl.java
public class OrcImpl implements Orc
{
	public void sayHello(String name)
	{
		System.out.println("hello~ " + name);
	}
	 
	public void orcGo(int direction)
	{
		switch (direction)
		{
			case __DIRECTION_NORTH:
				System.out.println("orc go NORTH..");		
			break;
			case __DIRECTION_SOUTH:
				System.out.println("orc go SOUTH..");		
			break;
			case __DIRECTION_EAST:
				System.out.println("orc go EAST..");		
			break;
			case __DIRECTION_WEST:
				System.out.println("orc go WEST..");		
			break;
		}
	}
}

main Method
public class RunTest
{
	public static void main(String[] args)
	{
		Orc orc = new OrcImpl();
		orc.sayHello("xxx");
		orc.orcGo(Orc.__DIRECTION_EAST);
	}
}

실행결과
hello~ xxx
orc go EAST..

  • 그런데 문제가 생겼습니다. 오크의 대도시인 오그리마 동쪽에 전쟁이 터졌습니다.!!
  • 오크에게 동쪽으로 이동할때 주의를 주는 메세지를 포함해야 합니다.
  • 이것을 DynamicProxy를 사용하여 구현하기 위해 다음과 같은 goEastAlertProxy를 구현합니다.

goEastAlertProxy.java
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class goEastAlertProxy implements java.lang.reflect.InvocationHandler
{
	private Object obj;
	private goEastAlertProxy(Object obj)
	{ this.obj = obj; }

	public static Object newInstance(Object obj)
	{
		return java.lang.reflect.Proxy.newProxyInstance(obj.getClass()
				.getClassLoader(), obj.getClass().getInterfaces(),
				new goEastAlertProxy(obj));
	}

	public Object invoke(Object proxy, Method m, Object[] args) throws Throwable
	{
		Object result;
		try
		{
			result = m.invoke(obj, args);
			
			if(m.getName().equals("orcGo"))
			{
				if(String.valueOf(args[0]).equals((String.valueOf(Orc.__DIRECTION_EAST))))
				{
					System.out.println("No! East!!");
				}
			}
		}
		catch (InvocationTargetException e)
		{
			throw e.getTargetException();
		}
		catch (Exception e)
		{
			throw new RuntimeException("unexpected invocation exception:"
					+ e.getMessage());
		}
		finally
		{
			
		}
		return result;
	}
}

실행코드

public class RunTest
{
	public static void main(String[] args)
	{
		Orc orc = new OrcImpl();
		orc.sayHello("xxx");
		orc.orcGo(Orc.__DIRECTION_EAST);
		
		System.out.println("======================================");
		
		Orc orcProxy = (Orc)goEastAlertProxy.newInstance(new OrcImpl());
		orcProxy.sayHello("xxx");
		orcProxy.orcGo(Orc.__DIRECTION_EAST);
	}
}


결과
hello~ xxx
orc go EAST..
======================================
hello~ xxx
orc go EAST..
No! East!!


  • 여기서 Target은 OrcImpl
  • JointPoint는 메소드가 끝나는 지점
  • PointCut은 goOrc 라는 이름을 가진 메소드
  • Advice는 "No! East!! 라는 메세지를 남기는 부분
  • Aspect는 goEastAlertProxy 정도로 살펴 볼 수 있습니다.
  • weaving은 내부적으로 JDK reflect API들이 해주고 있구요.

  • AOP에 필요한 개념을 간단한 DynamicProxy 예제로 살펴봤습니다. ^^