Spring-AOP源码-ProxyFactory


跳转查看ProxyFactory的使用

ProxyFactory是Spring-AOP中非常核心的类,如果不懂ProxyFactory,就无法彻底理解Spring-AOP

1. 创建代理入口:ProxyFactory#getProxy

  1. ProxyFactory#getProxy()
	public Object getProxy() {
		return createAopProxy().getProxy();
	}
  1. ProxyFactory#createAopProxy()
  • activate()`方法可以忽略: 只是回调了ProxyFactory的Listener, Spring未使用到该扩展点
  • getAopProxyFactory() : AopProxyFactory是一个 接口, 只有一个实现类DefaultAopProxyFactory
    所以继续跟踪DefaultAopProxyFactory
	protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		return getAopProxyFactory().createAopProxy(this);
	}

2. DefaultAopProxyFactory

  1. DefaultAopProxyFactory#createProxy()
  • if中有三个判断条件
    - isOptimize(): 默认false, 是否考虑优先采用Cglib, 因为Cglib的性能高于JDK的Proxy
    - isProxyTargetClass(): 默认false, 是否基于类的代理
    - hasNoUserSuppliedProxyInterfaces(): 根据被代理类的接口判断, 如果没有实现任何接口, 那么也采用Cglib
	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.");
			}
			// 1.当前类就是接口
			// 2.当前类就是Proxy对象: 这种情况很罕见
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

本次以跟踪JdkDynamicAopProxy的源码为主,ObjenesisCglibAopProxyJdkDynamicAopProxy的逻辑大同小异
JdkDynamicAopProxy相对来说简单易读一些

3. JdkDynamicAopProxy

1. 构造方法

构造参数的 config 实际上就是 ProxyFactory , ProxyFactory 继承了 AdvisedSupport

等价为: this.advised = proxyFactory

	public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
		// 忽略异常判断...
		
		this.advised = config;
	}
2. JdkDynamicAopProxy#getProxy()创建代理

直接调用了Jdk的Proxy类创建了代理对象,且第三个参数InvocationHandler就是当前对象

那么执行代理对象的任何方法都会执行到当前对象的invoke()方法

	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		// 计算出来需要实现哪些接口
		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);

		// 看看是否有重写了equals/hashcode, 仅仅为了优化
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);

		// handler就是自己, 真正调用时会执行当前对象的invoke方法
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}

此刻,代理对象已经创建成功了
接下来应该取分析invoke()方法了,代理对象的任何方法执行前都会执行invoke()方法

3. JdkDynamicAopProxy#invoke()
  1. 调用的是equals()方法,那么直接调用JdkDynamicAopProxy#equals,不执行Aspect增强
  2. 调用的是hashcode()方法,那么直接调用JdkDynamicAopProxy#hashcode,不执行Aspect增强
  3. 调用的是DecoratingProxy#getDecoratedClass()方法,那么直接返回当前被代理对象的class类型
    • 条件1:this.advised.opaque == false
      前面构造方法有说过, this.advised其实就是proxyFactory, 且proxyFactoryopaque默认就为false;
      什么情况下opaque属性需要被设置为true呢? 当你希望Advised 接口的方法调用也被Advice增强时, 可以给proxyFactory#opaque设置为true
    • 条件2:调用的是Advised 接口里的方法,( Spring创建代理时, 会给被代理类实现Advised 接口 ), Spring创建的代理对象都可以被强制转换为Advised
  4. exposeProxy是否为true ( 默认false ) ;
    如果为true, 暴露当前的代理对象, 使调用者可以通过调用AopContext#currentProxy()方法获取到当前的代理对象
  5. 获取当前被代理对象的class ;
    值得一提的是,通常使用ProxyFactory时,没有给targetSource赋值, 那么targetSource是怎么来的呢?
    根据proxyFactory#setTaget方法可知, proxyFactory会将被代理的目标对象封装成SingletonTargetSource赋值给targetSource属性
  6. 组装拦截器链, 核心方法,将proxyFactory中的advisor封装成拦截器链, 对被代理对象的方法进行拦截
	@Override
	@Nullable
	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 {
			// 1. 调用了equlas() 方法
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				return equals(args[0]);

			// 2. 调用的是hashCode方法
			} else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
				return hashCode();
	
			// 3. 调用的是DecoratingProxy#getDecoratedClass()方法
			} else if (method.getDeclaringClass() == DecoratingProxy.class) {
				return AopProxyUtils.ultimateTargetClass(this.advised);

			// 4. advised的opaque属性为false && 调用的是Advised接口里的方法
			} else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
					method.getDeclaringClass().isAssignableFrom(Advised.class)) {
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal;
		
			// 5. 是否期望暴露当前代理的对象
			if (this.advised.exposeProxy) {
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}

			// 6. 获取被代理的对象的class, targetSource在方法最开始被赋值
			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);
			
			// 7. 组装拦截器链
			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();
			
			// return this 的特殊处理
			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()) {
				// ignore : 空实现
				targetSource.releaseTarget(target);
			}
			if (setProxyContext) {
				// 还原AopContext的currentProxy
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}
4. 组装拦截器链

组装拦截器链的主要目的为:

将可以被使用的的advice统一转换为MethodInterceptor列表 ( List<MethodInterceptor> )

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

注意:这里的this.advised其实就是proxyFactory,这个关键点在构造方法时也提到过
proxyFactory中包含了所有的advisoradvice,还有一些其他的属性,例如exposeProxy,frozen

其实给proxyFactory添加Advice时,Advice也会被包装成Advisor

附带ProxyFactory#addAdvice源码

	@Override
	public void addAdvice(int pos, Advice advice) throws AopConfigException {
		if (advice instanceof IntroductionInfo) {
			addAdvisor(pos, new DefaultIntroductionAdvisor(advice, (IntroductionInfo) advice));
		}
		else if (advice instanceof DynamicIntroductionAdvice) {
			throw new AopConfigException("DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor");
		}
		else {
			addAdvisor(pos, new DefaultPointcutAdvisor(advice));
		}
	}
5. getInterceptorsAndDynamicInterceptionAdvice
	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable 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;
	}

可以看到,这里还没有组装拦截器链条,只是有一层缓存的逻辑
真正组装拦截件器链条委托给了advisorChainFactory

6. advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice
	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;

		for (Advisor advisor : advisors) {
			if (advisor instanceof PointcutAdvisor) {
				PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
				if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
					
					MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
					
					boolean match;
					
					/*** 忽略这段逻辑, 没必要细, 这里牵扯到`AspectJ`的`Pointcut`表达式匹配的`maybeMatch`的分支
					if (mm instanceof IntroductionAwareMethodMatcher) {
						if (hasIntroductions == null) {
							hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
						}
						match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
					}
					*/
					else {
						match = mm.matches(method, actualClass);
					}
					if (match) {
						MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
						/*** 忽略这段逻辑,没必要细究,因为有些`advisor`需要在运行时判断是否可以匹配
						if (mm.isRuntime()) {
							for (MethodInterceptor interceptor : interceptors) {
								interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
							}
						}*/
						else {
							// 添加到 { interceptorList } 中
							interceptorList.addAll(Arrays.asList(interceptors));
						}
					}
				}
			}
			// 忽略这两个分支
			else if (advisor instanceof IntroductionAdvisor) { /* ... */ }
			else { /* ... */ }
		}

		// 返回 { interceptorList }
		return interceptorList;
	}
  1. AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

AdvisorAdapterRegistry 是一个适配器,用于将Advice接口下的实现类转换为MethodInterceptor

  1. Advisor[] advisors = config.getAdvisors();

config其实就是ProxyFactory,获取ProxyFactory的所有advisor

  1. List<Object> interceptorList = new ArrayList<>(advisors.length);

用于作为方法结果返回的,也就是真正的执行器链对象

  1. if (advisor instanceof PointcutAdvisor)

99%的情况下都是这个分支,例如我们直接使用@Pointcut注解为Aspect声明切入点时,Aspect就会被包装为PointcutAdvisor

  1. if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass))

isPreFiltered()一个优化点,如果提前检查过了,那么就不再通过ClassFilter再检查一次
在ProxyFactory使用篇章中有提到过,PointcutAdvisorPointcut可以基于类和方法判断是否进行切入,此刻就是在判断类是否匹配

  1. match = mm.matches(method, actualClass);

判断方法是否匹配

  1. MethodInterceptor[] interceptors = registry.getInterceptors(advisor);

将advisor转换为MethodInterceptor[]

  1. 如果advisor的advice本身就是MethodInterceptor,那么直接返回
  2. 否则使用AdvisorAdapterRegistry registry适配器进行适配,将advice转换为methodInterceptor

为什么一个advisor可以被转换成一个MethodInterceptor[]数组呢?

因为一个advice可能即实现了BeforeAdvice,又实现了AfterAdvice,那么这个advice就会被包装成两个MethodInterceptor

7. 回到invoke()方法
	@Override
	@Nullable
	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 {
			// 1. 调用了equlas() 方法
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				return equals(args[0]);

			// 2. 调用的是hashCode方法
			} else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
				return hashCode();
	
			// 3. 调用的是DecoratingProxy#getDecoratedClass()方法
			} else if (method.getDeclaringClass() == DecoratingProxy.class) {
				return AopProxyUtils.ultimateTargetClass(this.advised);

			// 4. advised的opaque属性为false && 调用的是Advised接口里的方法
			} else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
					method.getDeclaringClass().isAssignableFrom(Advised.class)) {
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal;
		
			// 5. 是否期望暴露当前代理的对象
			if (this.advised.exposeProxy) {
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}

			// 6. 获取被代理的对象的class, targetSource在方法最开始被赋值
			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);
			
			// 7. 组装拦截器链
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
		
			// 8. 没有适用的 { advice }
			if (chain.isEmpty()) {
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				// 直接执行方法
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			} else {
			// 9. 有适用的 { advice }, 包装为 { MethodInvocation }
				MethodInvocation invocation =
						new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
			// 10. 调用 { MethodInvocation } , 获取结果
				retVal = invocation.proceed();
			}

			Class<?> returnType = method.getReturnType();
			
			// return this 的特殊处理
			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);
			}
			
			// 11. 返回结果
			return retVal;
		} finally {
			if (target != null && !targetSource.isStatic()) {
				// ignore : 空实现
				targetSource.releaseTarget(target);
			}
			if (setProxyContext) {
				// 还原AopContext的currentProxy
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}
8. ReflectiveMethodInvocation#proceed
	public Object proceed() throws Throwable {

		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			return invokeJoinpoint();
		}
		
		Object interceptorOrInterceptionAdvice =
				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
		
		/*** 忽略这段逻辑,没有必要深究, 上面也提到过, 有些 { advisor } 需要在运行时判断是否匹配, 匹配上了才执行增强
		if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
			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 {
				// 没有匹配上, 递归调用当前方法 { proceed }, 执行下一个拦截器
				return proceed();
			}
		}
		*/
		else {
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}
  1. 拦截器已经执行完了
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			// { invokeJoinpoint }其实就是通过反射直接调用了方法, 没有其他的逻辑
			return invokeJoinpoint();
		}
  1. 通过索引获取到下一个拦截器
Object interceptorOrInterceptionAdvice =
				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
  1. 调用MethodInterceptor#invokeMethodInterceptor的使用可以跳转查看ProxyFactory的使用
	return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);

至此,ProxyFactory创建代理以及代理对象方法的执行已经彻底完结了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值