MethodInvocationImpl.java
package sprout.aop;
import net.sf.cglib.proxy.MethodProxy;
import sprout.aop.advisor.Advisor;
import java.lang.reflect.Method;
import java.util.List;
public class MethodInvocationImpl implements MethodInvocation{
private final Object target; // 실제 메서드가 호출될 대상 객체
private final Method method; // 호출될 메서드의 Method 객체
private final Object[] args; // 메서드 호출 인자
private final MethodProxy methodProxy; // CGLIB의 메서드 프록시 (실제 타겟 메서드 호출용)
private final List<Advisor> advisors; // 현재 적용 가능한 어드바이저 목록
private int currentAdvisorIndex = -1; // 현재 실행할 어드바이저의 인덱스
public MethodInvocationImpl(Object target, Method method, Object[] args, MethodProxy methodProxy, List<Advisor> advisors) {
this.target = target;
this.method = method;
this.args = args;
this.methodProxy = methodProxy;
this.advisors = advisors;
}
@Override
public Signature getSignature() {
return new MethodSignature(method); // MethodSignature 객체를 사용하여 시그니처 정보 제공
}
@Override
public Object getTarget() {
return target;
}
@Override
public Object[] getArgs() {
return args;
}
@Override
public Method getMethod() {
return method;
}
@Override
public Object[] getArguments() {
return args;
}
@Override
public Object proceed() throws Throwable {
currentAdvisorIndex++; // 다음 어드바이저로 이동
if (currentAdvisorIndex < advisors.size()) {
// 다음 어드바이저의 Advice 실행
Advisor advisor = advisors.get(currentAdvisorIndex);
// advisor.getAdvice()는 sprout.aop.advice.Advice 인터페이스를 반환해야 합니다.
// Advice 인터페이스는 invoke(ProceedingJoinPoint pjp)를 가집니다.
return advisor.getAdvice().invoke(this);
} else {
// 모든 어드바이저를 실행했으면 실제 타겟 메서드 호출
return methodProxy.invoke(target, args);
}
}
}