AOP는 프레임워크나 아키텍쳐보다는 패러다임에 더 가깝기 때문에 굳이 AOP 전용 언어가 아니더라도 그 의미를 살리는데는 큰 무리가 없다.
이를테면 Javascript의 경우
AOP = {
addBefore : function(obj, fname, before) {
var oldFunc = obj[fname];
obj[fname] = function() {
before(arguments, obj);
return oldFunc.apply(this,arguments);
};
},
addAfter : function(obj, fname, after) {
var oldFunc = obj[fname];
obj[fname] = function() {
result = oldFunc.apply(this, arguments);
try{
return result;
} finally{
after(result, arguments, obj);
}
};
}
};
// example 1
function setRed(o){
o.style.color = "red";
}
function altBeforeAdvisor(args, targetObject){
alert("before");
}
AOP.addBefore(this, "setRed", altBeforeAdvisor);
// example 2
function setBlue(o){
o.style.color = "blue";
}
function altAfterAdvisor(result, args, targetObject){
alert("after");
}
AOP.addAfter(this, "setBlue", altAfterAdvisor);
와 같이 비교적 쉽게 구현할 수 있다.
좀더 나은 예제는
에서 볼수 있다.
자바에서 AOP을 적용 하는 것은 생각보다 쉽지 않다.
http://www.voelter.de/data/articles/aop/aop.html 와 같이 AspectJ언어를 사용하지 않는다면 말이다.
스프링처럼 AOP패러다임을 제공하는 프레임워크를 만들기 위해서는 약간의 테크니컬한 기술이 필요하다. 가장 쉽게는 데코레이터 패턴을 생각해 볼 수 있다. 이러 상황에서 상속은 좀 위험하기 때문에 현명한 선택이 아니다.
다소 복잡하지만 Proxy를 사용할 수도 있다.
먼저 Proxy객체는 InvacationHandler를 구현해야 한다.
package com.bleujin.thinlet.sample.invocation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class NumObjectHandler implements InvocationHandler{
private Object target ;
NumObjectHandler(Object target){
this.target = target ;
}
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
System.out.println(m.getName());
return m.invoke(target, args);
}
} |
NumObjectHandler 클래스는 모든 메소드의 호출전에 System.out.println(m.getName());를 실행시켜 준다.
package com.bleujin.thinlet.sample.invocation;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
public class TestInvoke extends TestCase {
public void testSum() throws Exception {
TestInvoke iv = new TestInvoke() ;
// NumObject n3 = new NumObject(3);
// NumObject n5 = new NumObject(5);
NumObject no3 = new NumObject(3);
NumObject no5 = new NumObject(5);
INum n3 = (INum)Proxy.newProxyInstance(new SimpleClassLoader(""), no3.getClass().getInterfaces(), new NumObjectHandler(no3)) ;
INum n5 = (INum)Proxy.newProxyInstance(new SimpleClassLoader(""), no5.getClass().getInterfaces(), new NumObjectHandler(no5)) ;
iv.add(n3);
iv.add(n5);
assertEquals(8, iv.sum()) ;
}
private int sum() {
int result = 0 ;
for (Object obj : data) {
result += ((INum)obj).getValue() ;
}
return result;
}
private List<Object> data = new ArrayList<Object>() ;
private void add(INum numObject) {
data.add(numObject) ;
}
}
를 |