Spring AOP源码分析十二

到目前为止,我们详细分析了jdk动态代理创建的整个流程,以及jdk动态代理执行的整个流程。我们知道,AOP代理其实分为jdk代理和cglib代理,接下来我们就要开始分析cglib代理,我们简单来回顾一下,我们看下边这张图:
在这里插入图片描述
这里最重要的其实就是config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)这行代码了。首先config.isOptimize()表示是否开启了优化策略,这个默认为false。接着是config.isProxyTargetClass(),如果这个属性为true的话,就代表是需要基于类进行代理的,说白了就是使用cglib代理的意思,而如果为false的话,那么就代表基于接口代理,也就是使用jdk代理。而最后一个条件hasNoUserSuppliedProxyInterfaces(config),简单来说,要不就是目标类没有实现接口 ,要不就是目标类实现了接口且接口类型是SpringProxy,这两种情况只要满足一种就会返回true。当这三个条件都为false时,也就是既没有开启优化策略,也没有设置基于类的代理,最后目标类实现了接口但不是SpringProxy类型的,此时就会使用jdk动态代理,如下图:
在这里插入图片描述
那么一旦三个条件中有一个为true,就会走到if分支里边去,但是代码执行到这里的时候,也不是说百分之百就使用cglib代理,因为这里还有一个if判断,如下图:
在这里插入图片描述
通过上图,可以看到,这里会再次判断下,目标类是不是本身就是一个接口或者代理类,那如果目标类本身就是一个接口或者代理类的话,这里还是会使用jdk代理的,其他情况则都会使用cglib代理了。这里简单总结一下,常见的几种情况,一般会怎么来选择代理,如下:
1、如果设置了proxyTargetClass为true,也就是设置了基于类进行代理,并且此时目标类本身既不是接口类型也不是代理类时,这个时候就会使用cglib代理
2、如果没有设置proxyTargetClass,即proxyTargetClass为false,但是此时目标类没有实现接口,此时也会使用cglib代理
3、如果目标类实现了接口,并且此时没有强制设置使用cglib代理,比如proxyTargetClass为false,这个时候就会使用jdk代理
由于我们目前既没有开启优化策略,也没有设置基于类的代理,并且目标类实现了接口但不是SpringProxy类型的,也就是说这三个条件全部为false,因此我们这里会使用jdk代理,也就是会执行这行代码,如下图:
在这里插入图片描述
通过刚才的分析,我们知道,按照目前配置的话,就会来创建jdk代理了,但是我们现在想来创建cglib代理,那么有没有什么办法呢?我们可以设置下proxyTargetClass属性为true,如下图:
在这里插入图片描述
一旦proxyTargetClass属性设置为true,那么就会执行下边这块代码,如下图:
在这里插入图片描述
由于我们的目标类targetClass既不是接口,也不是代理类,所以就会执行return new ObjenesisCglibAopProxy(config)这行代码来创建cglib代理了!我们来进一步看下ObjenesisCglibAopProxy类的构造方法,代码如下:
在这里插入图片描述
在这里插入图片描述
通过上图,我们可以看到,其实ObjenesisCglibAopProxy依赖父类CglibAopProxy的构造方法完成初始化,这里最关键的,其实就是将创建代理的核心配置config赋值给了成员变量advised,这样就成功构造出来了一个ObjenesisCglibAopProxy类的实例了。而之前我们也讲过,其实这个config就是一个ProxyFactory,并且这个ProxyFactory中封装了很多创建代理相关的核心属性,比如和目标类相匹配的增强,代理类需要实现的接口等等。目前为止呢,我们只是构建了一个ObjenesisCglibAopProxy对象,而不是一个真正的cglib代理,那么真正的cglib代理该怎么生成呢?我们看下边这块代码:
在这里插入图片描述
在创建完ObjenesisCglibAopProxy对象后,接下来就要调用getProxy(classLoader)方法来真正创建cglib对象了。其实就是调用ObjenesisCglibAopProxy类中的getProxy(classLoader)方法。而这个ObjenesisCglibAopProxy类中的getProxy(classLoader)方法,是从父类CglibAopProxy继承过来的,如下图:
在这里插入图片描述
我们到CglibAopProxy类的getProxy(classLoader)方法代码如下:

	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
		}

		try {
			// 获取目标类,就是com.younger.springcloud.service.impl.UserServiceImpl
			Class<?> rootClass = this.advised.getTargetClass();
			Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

			Class<?> proxySuperClass = rootClass;
			if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
				proxySuperClass = rootClass.getSuperclass();
				Class<?>[] additionalInterfaces = rootClass.getInterfaces();
				for (Class<?> additionalInterface : additionalInterfaces) {
					this.advised.addInterface(additionalInterface);
				}
			}

			// Validate the class, writing log messages as necessary.
			validateClassIfNecessary(proxySuperClass, classLoader);

			// Configure CGLIB Enhancer...
			Enhancer enhancer = createEnhancer();
			if (classLoader != null) {
				enhancer.setClassLoader(classLoader);
				if (classLoader instanceof SmartClassLoader &&
						((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
					enhancer.setUseCache(false);
				}
			}
			// 设置代理类要继承的父类,proxySuperClass 其实就是 com.younger.springcloud.service.impl.UserServiceImpl
			enhancer.setSuperclass(proxySuperClass);
			enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
			enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));

			// 获取回调数组
			Callback[] callbacks = getCallbacks(rootClass);
			Class<?>[] types = new Class<?>[callbacks.length];
			for (int x = 0; x < types.length; x++) {
				types[x] = callbacks[x].getClass();
			}
			// fixedInterceptorMap only populated at this point, after getCallbacks call above
			enhancer.setCallbackFilter(new ProxyCallbackFilter(
					this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
			enhancer.setCallbackTypes(types);

			// Generate the proxy class and create a proxy instance.
			// 创建代理类和代理类实例
			return createProxyClassAndInstance(enhancer, callbacks);
		}
		catch (CodeGenerationException | IllegalArgumentException ex) {
			throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
					": Common causes of this problem include using a final class or a non-visible class",
					ex);
		}
		catch (Throwable ex) {
			// TargetSource.getTarget() failed
			throw new AopConfigException("Unexpected AOP exception", ex);
		}
	}

首先就是执行下边这块代码:
在这里插入图片描述
上边的代码,其实就是获取了目标类的class对象,说白了就是UserServiceImpl类的class对象。cglib是采用继承目标类,重写父类方法的形式实现的动态代理,所以当然需要指定代理类的父类了。获取到要继承的目标类后,我们接着往下看,此时会看到下边的代码:
在这里插入图片描述
通过上边的代码,我们可以看到,其实这里就是构造了一个Enhancer,然后为Enhancer设置了各种属性,比如通过enhancer.setSuperclass(proxySuperClass)这行代码,就设置了代理类要实现的父类。我们知道,对于Enhancer来说,除了设置要继承的父类外,还需要设置回调,其实就是callbacks,此时我们看到上边的代码中,有一行获取回调数组的方法,就是Callback[] callbacks = getCallbacks(rootClass),我们就来看看这里是怎么来获取回调数组的吧,此时getCallbacks()代码如下:

	private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
		// Parameters used for optimization choices...
		boolean exposeProxy = this.advised.isExposeProxy();
		boolean isFrozen = this.advised.isFrozen();
		boolean isStatic = this.advised.getTargetSource().isStatic();

		// Choose an "aop" interceptor (used for AOP calls).
		// AOP回调需要调用到的拦截器
		Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

		// Choose a "straight to target" interceptor. (used for calls that are
		// unadvised but can return this). May be required to expose the proxy.
		Callback targetInterceptor;
		if (exposeProxy) {
			targetInterceptor = (isStatic ?
					new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
					new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
		}
		else {
			targetInterceptor = (isStatic ?
					new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
					new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
		}

		// Choose a "direct to target" dispatcher (used for
		// unadvised calls to static targets that cannot return this).
		Callback targetDispatcher = (isStatic ?
				new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());

		// 创建拦截器数组
		Callback[] mainCallbacks = new Callback[] {
				aopInterceptor,  // for normal advice
				targetInterceptor,  // invoke target without considering advice, if optimized
				new SerializableNoOp(),  // no override for methods mapped to this
				targetDispatcher, this.advisedDispatcher,
				new EqualsInterceptor(this.advised),
				new HashCodeInterceptor(this.advised)
		};

		Callback[] callbacks;

		// If the target is a static one and the advice chain is frozen,
		// then we can make some optimizations by sending the AOP calls
		// direct to the target using the fixed chain for that method.
		if (isStatic && isFrozen) {
			Method[] methods = rootClass.getMethods();
			Callback[] fixedCallbacks = new Callback[methods.length];
			this.fixedInterceptorMap = new HashMap<>(methods.length);

			// TODO: small memory optimization here (can skip creation for methods with no advice)
			for (int x = 0; x < methods.length; x++) {
				Method method = methods[x];
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
				fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
						chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
				this.fixedInterceptorMap.put(method, x);
			}

			// Now copy both the callbacks from mainCallbacks
			// and fixedCallbacks into the callbacks array.
			callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
			System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
			System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
			this.fixedInterceptorOffset = mainCallbacks.length;
		}
		else {
			// 设置回调拦截器数组给 callbacks
			callbacks = mainCallbacks;
		}
		return callbacks;
	}

可以看到,这里就是先创建了一个DynamicAdvisedInterceptor拦截器的实例aopInterceptor。接着手动构建了一个回调数组mainCallbacks,将一堆拦截器放入这个回调数组中,其中就包括刚才创建的aopInterceptor拦截器,最后会将回调数组mainCallbacks赋值给callbacks并返回。而这个callbacks中的拦截器,就是cglib代理对象中的方法被调用时需要回调的拦截器,这些拦截器中,有一个极为重要的拦截器,那就是DynamicAdvisedInterceptor拦截器了。获取到回调数组之后,创建cglib代理的准备工作就完成了,此时就会执行下边这行代码:
在这里插入图片描述我们到createProxyClassAndInstance方法中看下:

@Override
	protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
		// 创建代理类
		Class<?> proxyClass = enhancer.createClass();
		Object proxyInstance = null;

		if (objenesis.isWorthTrying()) {
			try {
				// 创建代理类实例
				proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
			}
			catch (Throwable ex) {
				logger.debug("Unable to instantiate proxy using Objenesis, " +
						"falling back to regular proxy construction", ex);
			}
		}

		if (proxyInstance == null) {
			// Regular instantiation via default constructor...
			try {
				Constructor<?> ctor = (this.constructorArgs != null ?
						proxyClass.getDeclaredConstructor(this.constructorArgTypes) :
						proxyClass.getDeclaredConstructor());
				ReflectionUtils.makeAccessible(ctor);
				proxyInstance = (this.constructorArgs != null ?
						ctor.newInstance(this.constructorArgs) : ctor.newInstance());
			}
			catch (Throwable ex) {
				throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
						"and regular proxy instantiation via default constructor fails as well", ex);
			}
		}

		// 设置回调
		((Factory) proxyInstance).setCallbacks(callbacks);
		return proxyInstance;
	}

我们可以看到,这里首先调用Enhancer的createClass()方法生成了代理类proxyClass,接着使用生成的代理类proxyClass,通过newInstance()方法进一步生成了代理类的实例proxyInstance,最后将回调数组callbacks设置到代理类proxyInstance中。到这里,cglib代理才算是真正创建成功了,此时我们知道,在回调数组callbacks中,有一个极为重要的拦截器,那就是DynamicAdvisedInterceptor,当cglib代理类实例中的方法被调用时,那么就会回调到这个拦截器DynamicAdvisedInterceptor,此时这个拦截器就会开始执行增强方法和目标方法。而且这个DynamicAdvisedInterceptor其实是CglibAopProxy中的一个内部类,而DynamicAdvisedInterceptor的intercept()方法,代码如下:
在这里插入图片描述

		@Override
		@Nullable
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			Object oldProxy = null;
			boolean setProxyContext = false;
			Object target = null;
			TargetSource targetSource = this.advised.getTargetSource();
			try {
				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();
				// 获取目标类,其实就是 com.younger.springcloud.service.impl.UserServiceImpl
				Class<?> targetClass = (target != null ? target.getClass() : null);
				// 获取拦截器链
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
				Object retVal;
				// Check whether we only have one InvokerInterceptor: that is,
				// no real advice, but just reflective invocation of the target.
				// 如果拦截器为空,那么直接调用目标方法
				if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
					// 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 = methodProxy.invoke(target, argsToUse);
				}
				else {
					// We need to create a method invocation...
					// 现将拦截器包装到 CglibMethodInvocation中,然后在调用proceed()方法执行拦截器链
					retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
				}
				retVal = processReturnType(proxy, target, method, retVal);
				return retVal;
			}
			finally {
				if (target != null && !targetSource.isStatic()) {
					targetSource.releaseTarget(target);
				}
				if (setProxyContext) {
					// Restore old proxy.
					AopContext.setCurrentProxy(oldProxy);
				}
			}
		}

首先就会来执行下边这块代码,如下图:
在这里插入图片描述
通过上图,可以看到,就是用来获取目标类的,其实最终获取的这个目标类targetClass的值就是UserServiceImpl,在分析jdk代理的invoke()方法时,也有类似的代码。获取到目标类后,我们继续往下看,此时就会看到下边这行代码,如下图:
在这里插入图片描述
主要还是调用getInterceptorsAndDynamicInterceptionAdvice方法获取拦截器链,这个和JDk的是一样的。我们继续往下看,获取拦截器之后,就要执行下边这块代码了,如下图:
在这里插入图片描述
可以看到,这里的逻辑和jdk代理的逻辑差不多。就是先看下拦截器链chain是不是为空,如果为空的话,说明此时没有增强需要执行,那此时直接执行目标方法。而如果拦截器链chain不为空,那此时就需要来执行拦截器链中的增强方法了,此时就会执行下边这行代码了,如下图:
在这里插入图片描述
可以看到,这里先通过构造方法创建了一个CglibMethodInvocation类的实例,接着调用了这个实例的proceed()方法。我们先来看下这个构造方法都做了什么,代码如下:
在这里插入图片描述
在这里插入图片描述
我们可以看到,其实CglibMethodInvocation主要依赖于父类ReflectiveMethodInvocation的构造方法完成的初始化,其中比较重要的,就是将拦截器链chain最终赋值给了成员变量interceptorsAndDynamicMethodMatchers。在CglibMethodInvocation的实例构建完成后,下一步就要调用CglibMethodInvocation的proceed()方法了,如下图:
在这里插入图片描述
接下来要调用CglibMethodInvocation类的proceed()方法了,那这时候,我们来看下proceed()方法的代码呗,如下图:
在这里插入图片描述
大家可以看到,其实proceed()方法关键就一行代码,那就是super.proceed(),说白了就是依赖于父类的proceed()方法完成了功能。其实在子类CglibMethodInvocation的proceed()方法中,其实还是依赖于父类ReflectiveMethodInvocation的proceed()方法完成的功能,所以cglib在执行拦截器链时,本质还是调用了ReflectiveMethodInvocation的proceed()方法,其实和jdk代理执行拦截器链是一样的。最后当拦截器链执行完成后,对拦截器链的返回值,做简单处理后,直接作为结果进行返回,如下图:
在这里插入图片描述
到这里为止,cglib代理的执行流程就结束了,可以看到,其实cglib代理在执行时,核心的两大流程,即获取拦截器链和执行拦截器链,其实和之前分析jdk代理的流程是一样的。

完善AOP代理的执行流程图:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

youngerone123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值