【源码】Spring AOP 11 AopProxyFactory AopProxy

前言

这章节我们介绍代理创建器工厂 AopProxyFactory 和具体的代理创建器 AopProxy,它们真正负责代理对象的创建

AopProxyFactory

public interface AopProxyFactory {

	AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;

}
  • 代理创建器工厂接口
  • createAopProxy 方法基于 Advised 代理信息创建对应的代理创建器 AopProxy

DefaultAopProxyFactory

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

	// ...

	@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {

		/**
		 * 如果是指定了 optimize 或 proxyTargetClass 或 没指定代理接口
		 * 		则会尝试使用 CGLIB 代理,否则就 JDK 代理
		 */
		if (!NativeDetector.inNativeImage() &&
				(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
			Class<?> targetClass = config.getTargetClass();
			if (targetClass == null) {
				throw new AopConfigException("...");
			}
			// 如果当前指定的类是个接口或者是 Proxy 类,那继续 JDK 代理
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			// 否则就 CGLIB 了
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

	// ...

}
  • 众所周知,动态代理方式有两种,基于 JDK 的动态代理和基于 CGLIB 的动态代理
  • 此处就是基于代理配置选择创建对应的代理创建器,JdkDynamicAopProxyObjenesisCglibAopProxy

AopProxy

public interface AopProxy {

	// 获取代理对象
	Object getProxy();

	// 指定类加载器
	Object getProxy(@Nullable ClassLoader classLoader);

}

代理创建器,用于真正创建代理对象

JdkDynamicAopProxy

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {

	/** getProxy **/

	@Override
	public Object getProxy() {
		return getProxy(ClassUtils.getDefaultClassLoader());
	}

	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		// ...
		
		return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
	}

	/** invoke from InvocationHandler **/

	@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 {
			
			// ...

			Object retVal;

			// 暴露为当前线程可见(ThreadLocal)
			// 这里是暴露在 InvocationHandler 的调用线程中而不是创建代理的线程哦
			// 因此在通知方法中我们可以获取到 proxy 对象: AopContext#getCurrentProxy
			if (this.advised.exposeProxy) {
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}

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

			// 这个方法是 AdvisedSupport 提供的,委托给 DefaultAdvisorChainFactory 实现的
			// 获取指定类方法上的所有 Interceptor
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

			// 如果没有拦截链
			if (chain.isEmpty()) {
				// 参数处理并直接调原始方法
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			// 如果有就把当前方法和 Interceptors Chain 封装成 ReflectiveMethodInvocation
			// 这里就会产生 MethodInvocation#proeed 和 MehthodInterceptor#invoke 的递归
			else {
				MethodInvocation invocation =
						new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				retVal = invocation.proceed();
			}

			// ... 结果的一些处理
			
			return retVal;
		}
		// ...	
	}

}
  • JDK动态代理,即我们熟悉的 Proxy.newProxyInstance(classLoader, proxiedInterfaces, this)
  • 可以看到传入的 InvocationHandlerthis,这意味着代理的实际行为取决于 invoke 方法,invoke 方法大体概括:
    • 在进行一些必要的处理后,首先会把当前代理对象暴露到 ThreadLocal 中,我们可以使用 AopContext#getCurrentProxy 直接获取哦
    • 会基于父类方法 AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice 方法获取当前方法的拦截链,本质就是 Advisors 的匹配与适配
    • 对于拦截链为空的方法,直接执行即可,否则构造对应的 ReflectiveMethodInvocation,之前了解过,ReflectiveMethodInvocation 就是对整个代理方法的执行,其 proceed 方法会跟 MethodInterceptor#invoke 形成递归,最终执行使用拦截器
    • 处理结果并返回

CglibAopProxy

  • JDK动态代理 相对的,基于 CGLIB 的代理
  • 其底层依赖的是 Enhancer 相关 API
  • 这里使用的是它的子类 ObjenesisCglibAopProxy
  • 具体源码就不深入了解了

总结

至此,我们了解了

  • AOP 相关的核心组件和对应的 API 体系,比如 Advice Joinpoint Pointut Advisor
  • Advised 下我们了解了如何创建最终的代理对象,以及它的代理原理

接下来,就可以了解下,Spring AOP 是在什么阶段如何针对 bean 组件创建对应的代理对象的

序列图

get the proxy

getProxy

上一篇:【源码】Spring AOP 10 ProxyFactoryBean ProxyFactory AspectJProxyFactory

下一篇:【源码】Spring AOP 12 原理解读一

参考

【小家Spring】详解Spring AOP的底层代理JdkDynamicAopProxy和ObjenesisCglibAopProxy的源码分析(介绍CGLIB使用中的坑)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值