-
-
- 1 aop 代理如何執行的?
- 2 cglib代理分析
- 3 jdk代理分析
-
1 aop 代理如何執行的?
前兩編主要分析代理是怎麼建立,而且整過分析過程還是比較粗線條分析,真要非常詳細分析估計用兩編去寫遠遠還是不夠的,因為細節的内容實際太多了。另外我身有些細節我也不太了解。我通常比較關心整體的原理,然後慢慢深入分析,如果一開始就深入太多細節,恐怕很容易被繞進去出來。
2 cglib代理分析
直接debug進入代理

由上面的截圖,很明顯目前使用的是cglib的代理,也看到上一編曲在建立cglib 代理建立的那幾個攔截器,下面f5進去代理方法testAAA裡面,發現進入的是第一個攔截器
private class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
//advisor資訊
private final AdvisedSupport advised;
public DynamicAdvisedInterceptor(AdvisedSupport advised) {
this.advised = advised;
}
@Override
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 {
//目标對象内部的自我調用将無法實施切面中的增強,
//<aop:aspect-autoproxy expose-proxy = "true"/>
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<Object> 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())) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
//沒有任何advice 相當直接調用目标
retVal = methodProxy.invoke(target, argsToUse);
} else {
// We need to create a method invocation...
//傳入攔截鍊路,建立Invocation,然後調用proceed();
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
//處理傳回值
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
} finally {
if (target != null) {
releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
//省略一些代碼
}
CglibMethodInvocation.proceed 處理攔截調用鍊
@Override
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
//currentIndex 從-1開始遞增,直到調用完所有攔截器,再調用連接配接點
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - ) {
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)) {
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,傳入自身,以便攔截器回調自身的procced方法
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
//調用連接配接點
@Override
protected Object invokeJoinpoint() throws Throwable {
if (this.publicMethod) {
//調用目标方法
return this.methodProxy.invoke(this.target, this.arguments);
}
else {
//通過父類調用目标方法
return super.invokeJoinpoint();
}
}
上面截圖可以看到兩攔截器
public class ExposeInvocationInterceptor implements MethodInterceptor, PriorityOrdered, Serializable {
//省略部分代碼
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = invocation.get();
invocation.set(mi);
try {
return mi.proceed();
}
finally {
invocation.set(oldInvocation);
}
}
//省略部分代碼
}
MethodBeforeAdviceInterceptor
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
//省略一些代碼
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
//執行前置方法
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
//繼續執行下個攔截器
return mi.proceed();
}
}
AspectJAfterAdvice
public class AspectJAfterAdvice extends AbstractAspectJAdvice
implements MethodInterceptor, AfterAdvice, Serializable {
//省略一些代碼
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
//繼續執行下一個攔截器
return mi.proceed();
}
finally {
//調用後置advice
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
//省略一些代碼
}
3 jdk代理分析
了解jdk動态代理應該都知道,jdk動态代理是利用目标類的接口去建立代理類的;換句話來說就是jdk動态代理的目标類必須實作一個接口;上面的demo目标類不太适用于此;再弄一個測試接口及目标類
其實jdk aop的代理過程與cglib代理差别并是不是很大,我們都知道jdk動态代理回調接口為InvocationHandler,而cglib的回調接口為MethodInterceptor,其主要差别就在兩者口的實作上,後面的攔截過程是一樣的;下來看一下jdk 代理的InvocationHandler invoke方法的實作JdkDynamicAopProxy
@Override
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.
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// 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.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
// 這一段代碼跟cglib那邊的實作是一樣的,擷取比對的調用攔截鍊
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
//上面大部分代碼跟cglib的一樣
//下面該類是cglib裡用的CglibMethodInvocation的父類,内容基本是一樣的
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
到這裡spring aop代理的實作原理基介紹完了