通过第一篇文章我们已经知道了怎么生成代理对象,现在这篇文章我们来跟踪下源码怎么执行代理方法。一个简单的例子来探寻SpringAOP执行源码的主脉络(一):创建代理对象
我们调试可以发现,我们的代理对象内容如下
里面有两个Advisor,第一个应该是spring默认的,我们定义的增强器为
InstantiationModelAwarePointcutAdvisor
这个也就对应我们的
@Aspect@Componentpublic class MyAspect {@Pointcut("execution(public * com.suibibk.spring.service.*.*(..))")public void web() {}@Around("web()")public Object doAround(ProceedingJoinPoint pjp) throws Throwable {System.out.println("之前");Object obj =pjp.proceed();System.out.println("之后");return obj;}}
里面的doAround方法,是这个方法的包装。我们点击下一步,进入到这个代里对象的invoke方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object oldProxy = null;boolean setProxyContext = false;TargetSource targetSource = this.advised.targetSource;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;}// Get as late as possible to minimize the time we "own" the target,// in case it comes from a pool.target = targetSource.getTarget();Class<?> targetClass = (target != null ? target.getClass() : null);// Get the interception chain for this method.//这里就是获取两个增强器,第二个才是我们要的List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);// Check whether we have any advice. If we don't, we can fallback on direct// reflective invocation of the target, and avoid creating a MethodInvocation.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...//把全部信息都封装成一个MethodInvocation对象,然后调用proceed方法。MethodInvocation invocation =new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);// Proceed to the joinpoint through the interceptor 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);}}}
上面关键步骤都有中文注释,主要就是获取Advisor链,然后封装成一个MethodInvocation对象。我们调试进去。
@Override@Nullablepublic Object proceed() throws Throwable {// We start with an index of -1 and increment early.//这里是递归的返回出口if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();}//这里是获取当前的一个下标,也就是先加1,一开始是-1Object 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;Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());if (dm.methodMatcher.matches(this.method, 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.//这里把当前类对象传过去return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);}}
这里通过用巧妙的方式,把循环去掉,变成递归。其实就是记录一个下标,没执行一个Advisor就自增一次,等所有Advisor都执行完了后,才会去调用正真的被代理对象的业务逻辑方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();}
我们发现我们的Advisor不是InterceptorAndDynamicMethodMatcher,所以会进入后面的方法
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
@Overridepublic Object invoke(MethodInvocation mi) throws Throwable {MethodInvocation oldInvocation = invocation.get();invocation.set(mi);try {return mi.proceed();}finally {invocation.set(oldInvocation);}}
这里执行完业务操作后又调用了
return mi.proceed();
又回到了上面的方法,不过此时currentInterceptorIndex==0,所以自加后会取到第二个,第二个是我们的切面方法
@Overridepublic Object invoke(MethodInvocation mi) throws Throwable {if (!(mi instanceof ProxyMethodInvocation)) {throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);}ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);JoinPointMatch jpm = getJoinPointMatch(pmi);return invokeAdviceMethod(pjp, jpm, null, null);}
我们进到
invokeAdviceMethod(pjp, jpm, null, null);
看看是怎么执行我们的
@Around("web()")public Object doAround(ProceedingJoinPoint pjp) throws Throwable {System.out.println("之前");Object obj =pjp.proceed();System.out.println("之后");return obj;}
方法的
protected Object invokeAdviceMethod(JoinPoint jp, @Nullable JoinPointMatch jpMatch,@Nullable Object returnValue, @Nullable Throwable t) throws Throwable {return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));}
我们进入到
invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {Object[] actualArgs = args;if (this.aspectJAdviceMethod.getParameterCount() == 0) {actualArgs = null;}try {ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);// TODO AopUtils.invokeJoinpointUsingReflection//应该是在这里执行的return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);}catch (IllegalArgumentException ex) {throw new AopInvocationException("Mismatch on arguments to advice method [" +this.aspectJAdviceMethod + "]; pointcut expression [" +this.pointcut.getPointcutExpression() + "]", ex);}catch (InvocationTargetException ex) {throw ex.getTargetException();}});
aspectJAdviceMethod这个就是我们的doAround方法,这里是执行这个方法。这一个方法运行会跳到我们的
@Around("web()")public Object doAround(ProceedingJoinPoint pjp) throws Throwable {System.out.println("之前");Object obj =pjp.proceed();System.out.println("之后");return obj;}
执行第一条语句答应后会取执行我们的proceed()方法,这里会去执行我们的test()方法,然后又会跳到
//这里是递归的返回出口if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();}
这里的invokeJoinpoint()就是执行我们正真的方法
@Nullableprotected Object invokeJoinpoint() throws Throwable {return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);}
@Nullablepublic static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)throws Throwable {// Use reflection to invoke the method.try {ReflectionUtils.makeAccessible(method);//执行业务逻辑return method.invoke(target, args);}catch (InvocationTargetException ex) {// Invoked method threw a checked exception.// We must rethrow it. The client won't see the interceptor.throw ex.getTargetException();}catch (IllegalArgumentException ex) {throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +method + "] on target [" + target + "]", ex);}catch (IllegalAccessException ex) {throw new AopInvocationException("Could not access method [" + method + "]", ex);}}
执行完业务逻辑后又会跳回
@Around("web()")public Object doAround(ProceedingJoinPoint pjp) throws Throwable {System.out.println("之前");Object obj =pjp.proceed();System.out.println("之后");return obj;}
打印”之后”然后返回。然后就执行完了,总体来说还是比较简单的。
总之:主要的业务处理考的是每个Advisor里面的advice(通知)的invoke方法。所以后面我们看事务的代理对象执行逻辑也只需要看它的advisor里面的advice的invoke方法就可以了。
