转载

Spring源码阅读-AOP(二)

在上一篇文章中,我们已经知道springAOP解析配置文件的过程,在本篇文章我们将继续为大家解答下面的两个问题。
复制代码
  • 了解spring是如何产生的代理对象
  • springAOP产生的代理对象是怎么执行的。

Spring是如何产生的代理对象

如果有看过之前我写的Spring-IOC源码阅读就会知道,我们如果要产生一个代理对象就需要在对象初始化之后创建对应的代理对象,而要进行初始化之后的操作就需用用到BeanPostProcessor中的一个方法postProcessAfterInitialization---初始化之后调用。
而我们在上一篇文章中也提到了一个类叫AspectJAwareAdvisorAutoProxyCreator,这个类是在解析配置文件过程中产生的用于创建代理对象,因此我们阅读的入口,我们找下这个类及其父类中哪个类实现了postProcessAfterInitialization这个方法,就是创建代理对象的入口。
大家可以自己去找找,最终可以找到父类AbstractAutoProxyCreator实现了postProcessAfterInitialization,我们直接进到这个方法中。
复制代码
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(beanClass, beanName);

		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		// Create proxy here if we have a custom TargetSource.
		// Suppresses unnecessary default instantiation of the target bean:
		// The TargetSource will handle target instances in a custom fashion.
		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
		if (targetSource != null) {
			if (StringUtils.hasLength(beanName)) {
				this.targetSourcedBeans.add(beanName);
			}
			Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		return null;
	}
复制代码

在这个方法中我们就看到了,createProxy这个创建代理对象的方法,我们继续往下跟

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {

		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}

		// 创建代理工厂对象
		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);

		if (!proxyFactory.isProxyTargetClass()) {
			// 是否可能使用CGLib代理
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				// 查看beanClass对应的类是否含有InitializingBean.class/DisposableBean.class/Aware.class接口
				// 无则采用JDK动态代理,有则采用CGLib动态代理
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}
		// 获得所有关联的Advisor集合(该分支待补充)
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		// 获取使用JDK动态代理或者cglib动态代理产生的对象
		return proxyFactory.getProxy(getProxyClassLoader());
	}
复制代码

这里我们只需要关注最后一行代码,获取代理对象,继续往下面走

public Object getProxy(@Nullable ClassLoader classLoader) {
		return createAopProxy().getProxy(classLoader);
	}
复制代码

这里创建了一个代理对象工厂来创建代理对象,接着一直往下走可以找到DefaultAopProxyFacory中的createAopProxy方法

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
			Class<?> targetClass = config.getTargetClass();
			if (targetClass == null) {
				throw new AopConfigException("TargetSource cannot determine target class: " +
						"Either an interface or a target is required for proxy creation.");
			}
			// 如果目标类是接口或者是Proxy的子类,那么使用JDK动态代理方式生成代理对象
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			// 使用Cglib动态代理
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			// 默认使用jdk
			return new JdkDynamicAopProxy(config);
		}
	}
复制代码

这里我们就知道了这个工厂其实就是判断是用jdk还是用cglib生成代理对象。我们就看jdk生成代理对象的过程,这里会返回一个JdkDynamicAopProxy,用于创建代理对象,我们接着最上面的代码getProxy(),找到JdkDynamicAopProxy的getProxy方法

@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
		}
		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		// 调用JDK动态代理方法
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}

复制代码

看到这里,如果对动态代理有些了解的同学就应该很清楚了,Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);这行代码就是jdk创建动态代理对象的api。 这里需要注意到,这里创建代理对象中这个InvocationHandler穿的的this。这就意味着,这个类不用来创建代理对象而且用来执行代理对象。里面肯定有invoke方法。

总结

AOP创建代理对象其实就是AbstractAutoProxyCreator实现了BeanPostProcessor的postProcessAfterInitialization方法,在对象初始化完成之后通过jdk或者cglib创建代理对象。 到这里我们就对上面的第二个问题有了答案。下面我们进入最后一个问题

springAOP产生的代理对象是怎么执行的

通过上面的创建代理对象的过程我们知道JdkDynamicAopProxy这个类其实就是动态代理中InvocationHandler的实现类,我们看到这个类的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;
		Object target = null;

		try {
			。。。

			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.
			
			// 检查是否我们有一些通知。如果我们没有,我们可以直接对目标类进行反射调用,避免创建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.
				// 进入连接点
				// 执行AOP的拦截过程
				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);
			}
		}
	}
复制代码

这个执行过程一共有下面几个步骤

  • 获取执行链,this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)
    • 获取执行链其实就是遍历我们之前解析到的所有的AspectJPointcutAdvisor,然后通过里面的AspectJExpressionPointcut匹配到对应的类
      • 如果是动态调用则把通知增强类(5中增强类)和方法匹配类MethodMatcher封装成一个InterceptorAndDynamicMethodMatcher对象到列表中
      • 如果不是的话就直接添加到链表中
    • 最后返回.具体代码可以跟进去看DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice方法
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
			Advised config, Method method, @Nullable 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<>(config.getAdvisors().length);
		Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
		boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
		AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

		for (Advisor advisor : config.getAdvisors()) {
			if (advisor instanceof PointcutAdvisor) {
				// Add it conditionally.
				PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
				if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
					MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
					MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
					if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
						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;
	}
复制代码
  • 判断执行链如果是空的,那么说明不用拦截直接通过凡是执行目标类的方法
AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse)
复制代码
  • 如果执行链不为空,我们就把需要的信息封装到ReflectiveMethodInvocation中调用对应的process方法
public Object proceed() throws Throwable {
		// We start with an index of -1 and increment early.
		//如果执行到执行连的最后,则直接调用目标方法
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			return invokeJoinpoint();
		}

		// 得到集合中的 MethodInterceptor
		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)) {
				// 如果匹配调用 MethodInterceptor的invoke方法
				// 注意这里传入的参数是this 我们下面看一下 ReflectiveMethodInvocation的类型
				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.
			// 说明是适用于此目标方法的 直接调用 MethodInterceptor的invoke方法
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}

复制代码

这里会递归调用类型遍历执行链,如果是动态调用则每一次都需要匹配是否对应的方法,是则调用invoke方法,如果不是动态调用则直接调用对应的invoke方法。最后执行完成后返回结果。 而这里的invoke方法就是我们之前获取的5个增强方法,我们可以拿其中一个看下,就可以了解整个链执行的过程。首先我们看下AspectJAfterAdvice的invoke方法

@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		try {
			// 执行切入点方法
			return mi.proceed();
		}
		finally {
			// 调用最终通知的增强类方法
			invokeAdviceMethod(getJoinPointMatch(), null, null);
		}
	}
复制代码

因为是after方法,所有必须先把目标方法调用完之后才调用,因此如果执行链执行到这个方法,就会再次递归继续执行知道目标方法调用完成最后调用这个invokeAdviceMethod方法, 我们可以跟进去看下,最终会调到AbstractAspectJAdvice的invokeAdviceMethodWithGivenArgs方法

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
			// 利用反射,执行增强方法
			// method.invoke(obj,arg)
			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();
		}
	}
复制代码

这个方法的本质其实就是利用反射去执行增强方法

最后

至此我们就把springAOP的调用过程阅读完毕,主要流程就是获取调用JdkDynamicAopProxy的invoke方法,获取执行链,封装成ReflectiveMethodInvocation对象递归调用process方法,在这个方法中调用对应的增强类的invock方法,最终利用反射去执行增强方法。

结语

经过这两篇文章,我们就把springAOP主体流程的源码一起阅读了一遍,整个过程还是比较复杂的,其中类的关系也是比较乱,大家需要多加理解。到这里我们就将springIOC和AOP的源码基本都阅读完毕.大家在阅读的过程中如果有什么问题或者建议和意见可以直接给我留言,我也会不断的改进和回答大家的问题,我希望来阅读我的文章的同学都能从里面得到帮助,这才是我最想要的。最后预告下,接下去我们会进入SpringMvc的源码阅读希望,大家继续关注,谢谢观看!

原文  https://juejin.im/post/5dec8af76fb9a01610796825
正文到此结束
Loading...