應用場景
公共子產品抽象出來,簡單的AOP功能編織到子產品中
核心技術實作
動态代理,相關的攔截器都配置到了動态對象裡
JDK 動态代理
隻能代理實作接口的類
invoke裡封裝了aop的實作
CGLIB 位元組碼增強技術
可以直接代理類
對callback回調設定中,通過DynamicAdvisedInterceptor攔截器來實作AOP功能的
源碼解析
以JDK動态代理為例
JdkDynamicAopProxy
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//如果攔截器鍊為空,直接調用目标方法
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
//否則的話,從這裡開始調用
retVal = invocation.proceed();
}
}
invocation 這個的實作ReflectiveMethodInvocation 這個類
@Override
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
//如果攔截器調用完成,則調用目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
//比對這個方法是不是需要攔截,是的話,調用攔截器
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { //invoke執行攔截器
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
上面有一個問題,從邏輯來看,是調用了所有的攔截器,再調用目标方法,這個時候,有一個疑問,after 通知不是方法執行了,再調用這個攔截操作嘛,繼續往下看
before 攔截器的實作 MethodBeforeAdviceInterceptor
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}
after的實作 AspectJAfterAdvice
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
我們可以看到before和after有可差別的,before先執行攔截,再調用下一步的攔截,after是一直要調用目标方法執行了之後,才執行這個after的邏輯。這後邊是遞歸的邏輯。