public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Class> targetClass = null;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.// 沒有宣告equals方法,呼叫equals方法時,委託呼叫。return equals(args[0]);
}
elseif (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.// 沒有宣告hashCode方法,呼叫hashCode方法時,委託呼叫。return hashCode();
}
elseif (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.// 如果呼叫的方法是DecoratingProxy中的方法,因為其中只有一個getDecoratedClass方法,這裡直接傳回被裝飾的Class即可return AopProxyUtils.ultimateTargetClass(this.advised);
}
elseif (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// 代理不是不透明的,且是介面中宣告的方法,且是Advised或其父介面的方法,則直接呼叫構造時傳入的advised物件的相應方法// Service invocations on ProxyConfig with the proxy config...return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
// Make invocation available if necessary.// 如果暴露代理,則用AopContext儲存當前代理物件。用於多級代理時獲取當前的代理物件,一個有效應用是同類中呼叫方法,代理攔截器會無效。可以使用AopContext.currentProxy()獲得代理物件並呼叫。
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// May be null. Get as late as possible to minimize the time we "own" the target,// in case it comes from a pool.
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
// Get the interception chain for this// 這裡是關鍵,獲得攔截鏈chain,是透過advised物件,即config物件獲得的。
method.
List
publicvoidaddAdvice(int pos, Advice advice) throws AopConfigException {
Assert.notNull(advice, "Advice must not be null");
if (advice instanceof IntroductionInfo) {
// We don't need an IntroductionAdvisor for this kind of introduction:// It's fully self-describing.// 如果是引介,則加入引介advisor。(新增功能)
addAdvisor(pos, new DefaultIntroductionAdvisor(advice, (IntroductionInfo) advice));
}
elseif (advice instanceof DynamicIntroductionAdvice) {
// We need an IntroductionAdvisor for this kind of introduction.// jdk動態代理不支援動態引介thrownew AopConfigException("DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor");
}
else {
// 把advice轉換為advisor並新增,標的是DefaultPointcutAdvisor。
addAdvisor(pos, new DefaultPointcutAdvisor(advice));
}
}
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
// 鏈全部執行完,再次呼叫proceed時,傳回原始物件方法呼叫執行結果。遞迴的終止。return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 用currentInterceptorIndex記錄當前的interceptor位置,初值-1,先++再獲取。當再攔截器中呼叫invocation.proceed()時,遞迴進入此方法,索引向下移位,獲取下一個攔截器。if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// 如果是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)) {
// 匹配成功,執行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.// 如果是interceptor,則直接呼叫invoke。把自己作為invocation,以便在invoke方法中,呼叫invocation.proceed()來執行遞迴。或者invoke中也可以不執行invocation.proceed(),強制結束遞迴,傳回指定物件作為結果。return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
Callback[] callbacks = getCallbacks(rootClass)
enhancer.setCallbacks(callbacks);
private Callback[] getCallbacks(Class> rootClass) throws Exception {
// Parameters used for optimization choices...
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean isStatic = this.advised.getTargetSource().isStatic();
// Choose an "aop" interceptor (used for AOP calls).// 生成aopInterceptor,用於AOP呼叫,這是呼叫攔截器鏈的核心,詳看後面。
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
// Choose a "straight to target" interceptor. (used for calls that are// unadvised but can return this). May be required to expose the proxy.
Callback targetInterceptor;
// 下麵根據不同情況,傳回不同的Callback。// targetSource的isStatic為true表示targetSource中的target是靜態的不改變的,故直接快取target即可。// 為false則代表是動態的target,每次都需要getTarget來獲取,這兩種傳回不同的callback,以便後續執行時使用不同情況的target。// 而exposeProxy代表是否暴露代理物件到AopProxyContext中。// 為true代表暴露,false不暴露。都需要傳回不同的callback。// 故總共有四種callback,且四種callback都有一個processReturnType的過程,同JdkDynamicAopProxy中的處理傳回值。前面的操作也與JdkDynamicAopProxy中開始的目的相同。if (exposeProxy) {
targetInterceptor = isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());
}
else {
targetInterceptor = isStatic ?
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedInterceptor(this.advised.getTargetSource());
}
// Choose a "direct to target" dispatcher (used for// unadvised calls to static targets that cannot return this).// 直接呼叫target的callback
Callback targetDispatcher = isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();
// callbackFilter傳回的是callback的索引,用於呼叫這裡的索引值對應的callback。
Callback[] mainCallbacks = new Callback[] {
aopInterceptor, // for normal advice// 經過callbackFilter後,不需要被advice的物件,直接呼叫這個interceptor,效能最高。
targetInterceptor, // invoke target without considering advice, if optimizednew SerializableNoOp(), // no override for methods mapped to this
targetDispatcher,
// 呼叫advised中方法時,直接分配到advised中。this.advisedDispatcher,
// equals方法new EqualsInterceptor(this.advised),
// hashCode方法new HashCodeInterceptor(this.advised)
};
Callback[] callbacks;
// If the target is a static one and the advice chain is frozen,// then we can make some optimizations by sending the AOP calls// direct to the target using the fixed chain for that method.// 這是一個最佳化,如果target是個不可變的靜態物件,且advice鏈是固定不變的,則進行最佳化。內容見後面。if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = new HashMap(methods.length);
// TODO: small memory optimization here (can skip creation for methods with no advice)for (int x = 0; x < methods.length; x++) {
// 遍歷所有方法,傳回每個方法的攔截器鏈,併為每個方法生成一個包含攔截器鏈的callback。
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
// 註意,這個fixedInterceptorMap還與callbackFilter關聯,以便達到filter的目的。// 同時儲存索引到map中,以用於callbackFilter中傳回索引。this.fixedInterceptorMap.put(methods[x].toString(), x);
}
// Now copy both the callbacks from mainCallbacks// and fixedCallbacks into the callbacks array.// 聚合所有callback
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
// 標記fixedInterceptor的偏移量,也會傳入filter。this.fixedInterceptorOffset = mainCallbacks.length;
}
else {
callbacks = mainCallbacks;
}
return callbacks;
}
// aopInterceptor: DynamicAdvisedInterceptorprivatestatic final int AOP_PROXY = 0;
// targetInterceptor: 沒有advise的方法privatestatic final int INVOKE_TARGET = 1;
// noOp: SerializableNoOpprivatestatic final int NO_OVERRIDE = 2;
// targetDispatcher: isStatic ? StaticDispatcher : SerializableNoOpprivatestatic final int DISPATCH_TARGET = 3;
// advisedDispatcher: AdvisedDispatcherprivatestatic final int DISPATCH_ADVISED = 4;
// EqualsInterceptorprivatestatic final int INVOKE_EQUALS = 5;
// HashCodeInterceptorprivatestatic final int INVOKE_HASHCODE = 6;
// 其他索引直接透過fixedInterceptorMap獲得// 下麵邏輯基本對應JdkDynamicAopProxy中判斷邏輯publicintaccept(Method method){
if (AopUtils.isFinalizeMethod(method)) {
// 如果是final的方法,則傳回NO_OVERRIDE
logger.debug("Found finalize() method - using NO_OVERRIDE");
return NO_OVERRIDE;
}
if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
if (logger.isDebugEnabled()) {
logger.debug("Method is declared on Advised interface: " + method);
}
// advised上的方法,直接呼叫advised物件的對應方法return DISPATCH_ADVISED;
}
// We must always proxy equals, to direct calls to this.if (AopUtils.isEqualsMethod(method)) {
// 傳回呼叫equals
logger.debug("Found 'equals' method: " + method);
return INVOKE_EQUALS;
}
// We must always calculate hashCode based on the proxy.if (AopUtils.isHashCodeMethod(method)) {
// 傳回呼叫hashCode
logger.debug("Found 'hashCode' method: " + method);
return INVOKE_HASHCODE;
}
Class> targetClass = this.advised.getTargetClass();
// Proxy is not yet available, but that shouldn't matter.
List> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 判斷是否有攔截器鏈
boolean haveAdvice = !chain.isEmpty();
boolean exposeProxy = this.advised.isExposeProxy();
boolean isStatic = this.advised.getTargetSource().isStatic();
boolean isFrozen = this.advised.isFrozen();
if (haveAdvice || !isFrozen) {
// 如果有advice或者不是凍結的(不可改變的)// If exposing the proxy, then AOP_PROXY must be used.if (exposeProxy) {
if (logger.isDebugEnabled()) {
logger.debug("Must expose proxy on advised method: " + method);
}
// 如果需要暴露Proxy則傳回aop代理return AOP_PROXY;
}
String key = method.toString();
// Check to see if we have fixed interceptor to serve this method.// Else use the AOP_PROXY.if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(key)) {
// 透過fixedInterceptorMap獲得對應索引,傳回callback。if (logger.isDebugEnabled()) {
logger.debug("Method has advice and optimizations are enabled: " + method);
}
// We know that we are optimizing so we can use the FixedStaticChainInterceptors.int index = this.fixedInterceptorMap.get(key);
return (index + this.fixedInterceptorOffset);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Unable to apply any optimizations to advised method: " + method);
}
return AOP_PROXY;
}
}
else {
// See if the return type of the method is outside the class hierarchy of the target type.// If so we know it never needs to have return type massage and can use a dispatcher.// If the proxy is being exposed, then must use the interceptor the correct one is already// configured. If the target is not static, then we cannot use a dispatcher because the// target needs to be explicitly released after the invocation.if (exposeProxy || !isStatic) {
// 如果需要暴露,則要使用targetInterceptorreturn INVOKE_TARGET;
}
Class> returnType = method.getReturnType();
if (returnType.isAssignableFrom(targetClass)) {
// 如果傳回型別是被代理型別的父類或者介面,有可能是傳回this取用,需要用INVOKE_TARGET對傳回值做處理if (logger.isDebugEnabled()) {
logger.debug("Method return type is assignable from target type and " +
"may therefore return 'this' - using INVOKE_TARGET: " + method);
}
return INVOKE_TARGET;
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Method return type ensures 'this' cannot be returned - " +
"using DISPATCH_TARGET: " + method);
}
// 不需要攔截,直接傳回標的呼叫return DISPATCH_TARGET;
}
}
}
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
// 下麵這段程式碼在我們除錯Spring的時候回經常進來,特別是進入一個Bean的方法後再傳回上一級呼叫時,最常見的就是這裡。// 這段程式碼基本與JdkDynamicAopProxy的invoke方法一致public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Class> targetClass = null;
Object target = null;
try {
if (this.advised.exposeProxy) {
// 需要則暴露// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// May be null. Get as late as possible to minimize the time we// "own" the target, in case it comes from a pool...
target = getTarget();
if (target != null) {
targetClass = target.getClass();
}
// 獲取攔截器鏈
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,// no real advice, but just reflective invocation of the target.if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// 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.// 如果鏈是空且是public方法,則直接呼叫
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// We need to create a method invocation...// 否則建立一個CglibMethodInvocation以便驅動攔截器鏈
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
// 處理傳回值,同JDK動態代理
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null) {
releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
朋友會在“發現-看一看”看到你“在看”的內容