【十四】Spring源码分析之AOP----JdkDynamicAopProxy代理对象invoke调用

一、简介

AOP源码分析主要分为5个篇章:前面4篇已经讲了

1. 注册、实例化、初始化AnnotationAwareAspectJAutoProxyCreator

【十】Spring源码分析之AOP----注册、实例化、初始化AnnotationAwareAspectJAutoProxyCreator
2. 扫描容器中的切面,创建PointcutAdvisor对象
【十一】Spring源码分析之AOP----AnnotationAwareAspectJAutoProxyCreator扫描@Aspect,创建Advisor

3.解析pointcut切点的表达式,看该目标bean与哪些Advisor匹配

【十二】Spring源码分析之AOP----匹配出作用于被代理类Advisor

4.Spring源码分析之AOP----生成代理对象。

【十三】Spring源码分析之AOP----生成代理对象

5. 被代理类的方法一次调用流程。就是本篇。

jdk动态代理的时候,getBean得到的是代理对象。调用目标对象的方法前,都是调用的代理对象的invoke方法进行增强拦截。

源码:

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 {

            // 如果被代理的目标对象要执行equal方法
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				// The target does not implement the equals(Object) method itself.

                // 则执行JdkDynamicAopProxy(即代理对象)的equal方法。spring不对equal方法进行AOP拦截
				return equals(args[0]);
			}

            // spring不对hashCode方法进行AOP拦截。如果被代理的目标对象要执行hashCode方法,则执行JdkDynamicAopProxy(即代理对象)的hashCode方法。
			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);
			}

            // 如果被代理的目标对象实现了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;
			}

			// 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 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...
				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);
			}
		}
	}

做了3件事:

1.spring不对equal方法进行AOP拦截。如果被代理的目标对象要执行equal方法,则执行JdkDynamicAopProxy(即代理对象)的equal方法。

spring不对hashCode方法进行AOP拦截。如果被代理的目标对象要执行hashCode方法,则执行JdkDynamicAopProxy(即代理对象)的hashCode方法。

如果被代理的目标对象实现了Advised接口,直接用反射执行目标对象的方法。不做增强处理。

2.得到该方法的拦截链,创建一个方法调用器,并将拦截器链传入其中, 执行拦截器链。

3.返回方法执行结果

 二、得到方法拦截链

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

源码:AdvisedSupport类

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
		MethodCacheKey cacheKey = new MethodCacheKey(method);
		List<Object> cached = this.methodCache.get(cacheKey);
		if (cached == null) {
			cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
					this, method, targetClass);
			this.methodCache.put(cacheKey, cached);
		}
		return cached;
	}

做了1件事:

从方法拦截链缓存methodCache中看有不有该方法的拦截链,有就直接返回,没有则调用this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice( this, method, targetClass)得到方法拦截链,放入缓存中,并且返回。

2.1 创建方法拦截链getInterceptorsAndDynamicInterceptionAdvice

DefaultAdvisorChainFactory类的getInterceptorsAndDynamicInterceptionAdvice方法

源码:

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
			Advised config, Method method, Class<?> targetClass) {

		// This is somewhat tricky... We have to process introductions first,
		// but we need to preserve order in the ultimate list.
		List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
		Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
		boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
		AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

        // 遍历Advisor
		for (Advisor advisor : config.getAdvisors()) {

            // 如果该adivosr是PointcutAdvisor类型的
			if (advisor instanceof PointcutAdvisor) {
				// Add it conditionally.
				PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
				if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {

                    // 把Advisor转成拦截器interceptor
					MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
					
                    // 得到该advisor的pointcut的方法匹配器
                    MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
					
                    // 判断该Advisor的pointcut跟目标对象要执行的方法是否匹配
                    if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
                        //MethodMatcher在运行时是否需要做一些检测
						if (mm.isRuntime()) {
							// Creating a new object instance in the getInterceptors() method
							// isn't a problem as we normally cache created chains.
							for (MethodInterceptor interceptor : interceptors) {
								interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
							}
						}
						else {
							interceptorList.addAll(Arrays.asList(interceptors));
						}
					}
				}
			}
			else if (advisor instanceof IntroductionAdvisor) {
				IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
				if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
					Interceptor[] interceptors = registry.getInterceptors(advisor);
					interceptorList.addAll(Arrays.asList(interceptors));
				}
			}
			else {
				Interceptor[] interceptors = registry.getInterceptors(advisor);
				interceptorList.addAll(Arrays.asList(interceptors));
			}
		}

		return interceptorList;
	}

做了3件事:

1.遍历Advisor。

2.如果是Advisor是PointcutAdvisor类型:得到该Advisor的Pointcut,判断要执行的目标对象的方法是否被这个Advisor增强。如果运行时需要做一些检测,则往返回列表中加入InterceptorAndDynamicMethodMatcher封装后的拦截器。否则直接加入拦截器到返回列表。

3.如果Advisor是IntroducationAdvisor类型的,用该Advisor的classFilter判断目标对象的类是否被这个Advisor增强,是则得到拦截器,加入到返回列表

4.如果 Advisor既不是PointcutAdvisor类型也不是IntroducationAdvisor类型,则不用匹配,直接生成拦截器,加入到返回列表。

 三、执行拦截器invocation.proceed()

源码:ReflectiveMethodInvocation类

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);

        // 如果该拦截器是InterceptorAndDynamicMethodMatcher类型
		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.
    
				// 不匹配,则调用proceed,搞下一个拦截器
                return proceed();
			}
		}

        // 如果该拦截器不是InterceptorAndDynamicMethodMatcher类型,则直接调用该拦截器的invoke方法
		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);
		}
	}

做了3件事:

1.如果拦截器链为空,或者已经执行完了拦截器,则调用invokeJoinpoint方法直接AopUtils.invokeJoinpointUsingReflection反射调用目标对象的方法。

2.从第一个拦截器开始调用。如果该拦截器不是InterceptorAndDynamicMethodMatcher类型,则直接调用该拦截器的invoke方法。

3.如果该拦截器是InterceptorAndDynamicMethodMatcher类型,进行动态匹配,动态匹配失败,忽略该拦截器直接调用下一个拦截器,动态匹配成功则调用该拦截器的invoke方法。

四、执行的拦截器的内容

我debug的时候,上一步一共搞了6个拦截器的invoke方法

4.1 ExposeInvocationInterceptor类

源码:

public Object invoke(MethodInvocation mi) throws Throwable {
		MethodInvocation oldInvocation = invocation.get();
		invocation.set(mi);
		try {
			return mi.proceed();
		}
		finally {
			invocation.set(oldInvocation);
		}
	}

做了1件事:

invocation是该类的一个ThreadLocal<MethodInvocation>,表示的是当前aop方法的invocation。

直接调用proceed方法执行下一个拦截器。

4.2 AspectJAfterThrowingAdvice类

源码:

public Object invoke(MethodInvocation mi) throws Throwable {
		try {
			return mi.proceed();
		}
		catch (Throwable ex) {
			if (shouldInvokeOnThrowing(ex)) {
				invokeAdviceMethod(getJoinPointMatch(), null, ex);
			}
			throw ex;
		}
	}

做了2件事:

1.直接调用proceed方法,执行下一个拦截器。

2.如果抛出异常,调用invokeAdviceMethod方法去调用切面中后置异常增强注解@AfterThrowing注解修饰的方法

4.3 AfterReturningAdviceInterceptor类

该类是InterceptorAndDynamicMethodMatcher类型的

源码:

public Object invoke(MethodInvocation mi) throws Throwable {
		Object retVal = mi.proceed();
		this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
		return retVal;
	}

做了3件事:

1.直接调用proceed方法执行下一个拦截器

2.调用this.advice.afterReturning方法执行切面中@AfterReturning后置增强注解修饰的方法。

3.返回proceed方法的返回值。

 4.4 AspectJAfterAdvice类

该类是InterceptorAndDynamicMethodMatcher类型的

源码:

public Object invoke(MethodInvocation mi) throws Throwable {
		try {
			return mi.proceed();
		}
		finally {
			invokeAdviceMethod(getJoinPointMatch(), null, null);
		}
	}

做了2件事:

1.直接调用proceed方法执行下一个拦截器

2.finally中执行invokeAdviceMethod方法去调用切面中@After后置增强注解修饰的方法。

 4.5 AspectJAroundAdvice类

该类是InterceptorAndDynamicMethodMatcher类型的

源码:

public Object invoke(MethodInvocation mi) throws Throwable {

        // 如果该方法执行器MethodInvocation不是ProxyMethodInvocation类型的,则抛出异常。
		if (!(mi instanceof ProxyMethodInvocation)) {
			throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
		}
		ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;

        // 得到一个MethodInvocationProceedingJoinPoint类型的ProceedingJoinPoint
		ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);


		JoinPointMatch jpm = getJoinPointMatch(pmi);


		return invokeAdviceMethod(pjp, jpm, null, null);
	}

做了4件事:

1.如果该方法执行器MethodInvocation不是ProxyMethodInvocation类型的,则抛出异常。

2.得到一个MethodInvocationProceedingJoinPoint类型的ProceedingJoinPoint

3.得到JoinPointMatch

4.调用invokeAdviceMethod执行方法。

4.5.1  invokeAdviceMethod(pjp, jpm, null, null)

源码:

	protected Object invokeAdviceMethod(JoinPoint jp, JoinPointMatch jpMatch, Object returnValue, Throwable t)
			throws Throwable {

        // argBinding方法得到目标对象调用方法的入参
		return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
	}

invokeAdviceMethodWithGivenArgs源码:

protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
		Object[] actualArgs = args;
		if (this.aspectJAdviceMethod.getParameterTypes().length == 0) {
			actualArgs = null;
		}
		try {
			ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
			// TODO AopUtils.invokeJoinpointUsingReflection

            // this.aspectInstanceFactory.getAspectInstance()得到切面类的对象,即是@Aspect注解修饰的那个类的对象
			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();
		}
	}

做了2件事:

1.this.aspectInstanceFactory.getAspectInstance()得到切面类的对象,即是@Aspect注解修饰的那个类的对象

2.调用切面类的@Around环绕增强注解修饰的方法。环绕增强@Around注解修饰的方法再调用proceed的时候会执行下一个拦截器

 4.6 MethodBeforeAdviceInterceptor类

该类是InterceptorAndDynamicMethodMatcher类型的

源码:

	public Object invoke(MethodInvocation mi) throws Throwable {
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
		return mi.proceed();
	}

做了2件事:

1.this.advice.before方法执行@Before前置增强注解的内容。

2.调用proceed方法执行下一个拦截器

我debug的情况是这个拦截器执行完了过后,就执行目标对象的真实方法了。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值