spring5源码篇(10)——spring-aop代理过程

spring-framework 版本:v5.3.19

废话少说,上代码
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在spring-aop中,无论是xml还是注解还是硬编码配置的代理,最后都会通过proxyFactory去实现真正的代理。
proxyFactory的使用也很简单,给他一个target和一个advisor即可生成代理类。

target就是被代理对象,而 advisor 可以简单的理解成 advice + pointcut

1、ProxyFactory

所以proxyFctory是如何生成代理对象的?

追踪ProxyFactory.getProxy()方法
在这里插入图片描述

1.1、createAopProxy() 创建AopProxy

这里可能创建 CglibAopProxy 也可能创建 JdkDynamicAopProxy,分别对应两种不同的动态代理方式

AopProxy 由 AopProxyFactory生成,而spring默认的AopProxyFactory只有 DefaultAopProxyFactory 这一个实现。
在这里插入图片描述
通俗的说就是:如果目标对象至少实现了一个接口则使用jdk,反之使用cglib。同时也可配置 optimize = true 或者 proxyTargetClass = true 强制使用cglib代理。

1.2、getProxy() 创建代理对象

这里就是用cglib或者是jdk的方式去创建一个代理对象了。以jdk为例,其实就是我们平时使用jdk动态代理的代码。
JdkDynamicAopProxy.getProxy()
在这里插入图片描述
注意看 Proxy.newProxyInstance 的 InvocationHandler 传了this,说明 JdkDynamicAopProxy 同时也实现了 InvocationHandler 。
也就是最最最重要的代理逻辑就在 JdkDynamicAopProxy.invoke 方法。

1.3、JdkDynamicAopProxy#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 {
			//特殊方法以及对代理对象的配置信息进行操作,如不代理equals,hashCode
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				return equals(args[0]);
			}
			else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
				return hashCode();
			}
			else if (method.getDeclaringClass() == DecoratingProxy.class) {
				return AopProxyUtils.ultimateTargetClass(this.advised);
			}
			else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
					method.getDeclaringClass().isAssignableFrom(Advised.class)) {
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal;

			//如果配置 exposeProxy = true 则把当前代理对象放到线程ThreadLocalMap中
			// 当想要自己调自己同时代理不失效的时候可以配为true
			if (this.advised.exposeProxy) {
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}

			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);

			//匹配添加的advisor
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

			if (chain.isEmpty()) {
				//如果为空直接反射调用
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				//不为空则进行代理
				MethodInvocation invocation =
						new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				retVal = invocation.proceed();
			}

			//对返回值的检查及特殊情况的处理
			Class<?> returnType = method.getReturnType();
			if (retVal != null && retVal == target &&
					returnType != Object.class && returnType.isInstance(proxy) &&
					!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
				//特殊情况:当返回自身时,则返回代理后的对象
				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()) {
				targetSource.releaseTarget(target);
			}
			if (setProxyContext) {
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}

1.3.1、advised.getInterceptorsAndDynamicInterceptionAdvice() 匹配添加的advisor并转化成所需对象

在这里插入图片描述

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

		AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
		Advisor[] advisors = config.getAdvisors();
		List<Object> interceptorList = new ArrayList<>(advisors.length);
		Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
		Boolean hasIntroductions = null;

		//分 PointcutAdvisor、IntroductionAdvisor、其他 三个分支
		for (Advisor advisor : advisors) {
			if (advisor instanceof PointcutAdvisor) {
				//PointcutAdvisor分支
				PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
				//匹配 prefiltered 和 class
				if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
					//匹配 method
					MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
					boolean match;
					if (mm instanceof IntroductionAwareMethodMatcher) {
						//如果MethodMatcher是IntroductionAwareMethodMatcher的话,则用IntroductionAwareMethodMatcher.matches
						if (hasIntroductions == null) {
							hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
						}
						match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
					}
					else {
						//反之直接用MethodMatcher.matches
						match = mm.matches(method, actualClass);
					}
					if (match) {
						//如果匹配则将 advisor 转化成 MethodInterceptor[]
						MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
						if (mm.isRuntime()) {
							// 如果runtime为true,说明需要根据参数动态匹配,添加 InterceptorAndDynamicMethodMatcher
							for (MethodInterceptor interceptor : interceptors) {
								//InterceptorAndDynamicMethodMatcher = MethodInterceptor + MethodMatcher
								interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
							}
						}
						else {
							// 反之直接加到list
							interceptorList.addAll(Arrays.asList(interceptors));
						}
					}
				}
			}
			else if (advisor instanceof IntroductionAdvisor) {
				//IntroductionAdvisor分支
				IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
				//匹配 prefiltered 和 class
				if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
					// 如果匹配 将advisor转成Interceptor[] 放到list
					Interceptor[] interceptors = registry.getInterceptors(advisor);
					interceptorList.addAll(Arrays.asList(interceptors));
				}
			}
			else {
				//其他类型的Advisor分支
				Interceptor[] interceptors = registry.getInterceptors(advisor);
				interceptorList.addAll(Arrays.asList(interceptors));
			}
		}

		return interceptorList;
	}

至于是如何转化的,用了适配器模式。遍历所有 AdvisorAdapter,如果这个适配器可以转化,则进行转化。注意看,这里就算适配了也没有退出循环,也就是说一个advisor可能同时被多个适配器适配,这也就是为什么会返回数组的原因。
register.getInterceptors(advisor)
在这里插入图片描述
与其说转化advisor,我个人更喜欢理解成转化advice。
内置的适配器跟内置的advice是对应上的
在这里插入图片描述
以before为例
在这里插入图片描述
不过为什么没有环绕通知的适配器,因为我们用的AspectJAroundAdvice环绕通知本来就是一个MethodInterceptor
在这里插入图片描述

总之这一步会匹配符合的advisor并将其转化成所需对象(如MethodInterceptor)。匹配的逻辑根据advisor的类型分为三个分支:PointcutAdvisor、IntroductionAdvisor、其他,简单的说,他们的区别就是分别为匹配类和方法,匹配类,无需匹配直接添加。但无论是哪种分支,最终都会将advisor(直接或通过适配器)转化成 MethodInterceptor 或 InterceptorAndDynamicMethodMatcher。

1.3.2、invocation.proceed() 执行代理逻辑

在这里插入图片描述
为空的情况没什么好说的直接反射调用就是了。
不为空的情况下,会将所有代理所需要的变量封装成一个 MethodInvocation ,并递归调用proceed()执行代理逻辑。
invocation.proceed()
在这里插入图片描述
以beforeAdvice转化的MethodBeforeAdviceInterceptor为例看一下是如何递归的。
在这里插入图片描述
至此,proxyFactory的jdk代理就看完了,cglib的代理也是类似的。无非就是生成代理对象时所用的技术不同而已,像什么advisor,AdvisorAdapter,methodInterceptor,InterceptorAndDynamicMethodMatcher,methodInvocation,等都是一样的。

总结上面的内容粗略画了一个流程图:
在这里插入图片描述

2、DefaultAdvisorAutoProxyCreator

不过我们平时使用spring-aop的时候貌似没有用到proxyFactory。而是只需配置advisor bean或者使用aspectj注解配置切面就可以了。
比如这样
在这里插入图片描述
为什么这里容器得到了bean会是一个代理类呢?什么时候给他代理了?
答案就在import的 DefaultAdvisorAutoProxyCreator
在这里插入图片描述
DefaultAdvisorAutoProxyCreator 本质上是一个SmartInstantiationAwareBeanPostProcessor,即BeanPostProcessor。在容器启动的时候会增强bean,所谓的增强其实就是自动扫描容器中匹配的advisor,并代理目标bean。

postProcessAfterInitialization 方法的增强逻辑在其抽象父类AbstractAutoProxyCreator
在这里插入图片描述

3、AnnotationAwareAspectJAutoProxyCreator

在这里插入图片描述
而 AnnotationAwareAspectJAutoProxyCreator 与 DefaultAdvisorAutoProxyCreator 最大的区别就在于寻找容器所有的advisor时,所使用的方法不同。 AnnotationAwareAspectJAutoProxyCreator 重写了findCandidateAdvisors() 使其支持将 aspectj 注解的内容转化成 advisor。
在这里插入图片描述
所以如果我们只是import了 DefaultAdvisorAutoProxyCreator 是不会去解析 aspectJ 对应的aop注解的。
只有当import了 AnnotationAwareAspectJAutoProxyCreator 才会去解析。这也正是 @EnableAspectJAutoProxy 注解所做的事情。
在这里插入图片描述

由代码也可以看出,当使用了 AnnotationAwareAspectJAutoProxyCreator 就没必要再使用 DefaultAdvisorAutoProxyCreator 了,因为前者不仅会解析 aspectJ 的注解生成advisor,同时也会像后者一样扫描当前已有的 advisor。

除了上面两种AutoProxyCreator,spring中还有 BeanNameAutoProxyCreator(根据bean name去自动创建),AspectJAwareAdvisorAutoProxyCreator(xml配置的aspectJ切面),InfrastructureAdvisorAutoProxyCreator(Infrastructure相关,如事务管理)。当然也可以自己去继承AbstractAdvisorAutoProxyCreator自定义自动代理创建逻辑。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值