跳至主要內容

Spring AOP源码解析

向往2023年10月2日大约 11 分钟SpringAOP

概述

Spring AOP 核心是动态代理技术,以动态代理为基础,设计出一系列AOP的横切实现,如前置通知、返回通知、异常通知等。同时,Spring AOP还提供了一些列的Pointcut来匹配切入点,可以使用现有的切入点来设计横切面,也可以扩展相关Pointcut方法来实现切入需求。本文主要分成两部分,一个是代理对象的生成,一个是拦截器调用逻辑。

实现

代理对象生成过程

代理对象生成以ProxyFactory的设计为核心,相关类继承关系如下图所示:

image-20231013114000948

获取代理对象方法:ProxyFactoryBean#getObject

	public Object getObject() throws BeansException {
    //为Proxy代理对象配置Advisor链
		initializeAdvisorChain();
		if (isSingleton()) {
      //生成singleton代理对象
			return getSingletonInstance();
		}
		else {
			if (this.targetName == null) {
				logger.info("Using non-singleton proxies with singleton targets is often undesirable. " +
						"Enable prototype proxies by setting the 'targetName' property.");
			}
			return newPrototypeInstance();
		}
	}

ProxyFactoryBean#getSingletonInstance

	private synchronized Object getSingletonInstance() {
		if (this.singletonInstance == null) {
			this.targetSource = freshTargetSource();
			if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
				// Rely on AOP infrastructure to tell us what interfaces to proxy.
        //根据AOP框架来判断需要代理的接口
				Class<?> targetClass = getTargetClass();
				if (targetClass == null) {
					throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
				}
         //设置代理对象的接口
				setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
			}
       // 使用ProxyFactory生成需要的Proxy
			// Initialize the shared singleton instance.
			super.setFrozen(this.freezeProxy);
			this.singletonInstance = getProxy(createAopProxy());
		}
		return this.singletonInstance;
	}


	@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (!NativeDetector.inNativeImage() &&
				(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.");
			}
       //如果目标类是接口 或者代理类,使用JDK来生成Proxy
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
      //使用cglib进行代理
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

在AopProxy代理对象的生成过程中,首先要从AdvisedSupport对象中取得配置的目标对象,这个目标对象是实现AOP功能所必需的。一般而言,默认的方式是使用JDK来产生AopProxy代理对象,但是如果遇到配置的目标对象不是接口类的实现,会使用CGLIB来产生AopProxy代理对象,在使用CGLIB来产生AopProxy代理对象时,因为CGLIB是一个第三方的类库,本身不在JDK的基本类库中,所以需要在CLASSPATH路径中进行正确的配置,以便能够加载和使用。在Spring中,使用JDK和CGLIB来生成AopProxy代理对象的工作,是由JdkDynamicAopProxyCglibProxyFactory来完成的。

JdkDynamicAopProxy生成代理对象:

	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
		}
    //调用JDK生成Proxy
		return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
	}

CglibAopProxy#getProxy生成唯一代理对象

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

		try {
      //从Advised中获得在IoC容器中配置的对象
			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...
      //创建并配置CGLIB的Enhancer,这个Enhancer对象是CGLIB的主要操作类
			Enhancer enhancer = createEnhancer();
			if (classLoader != null) {
				enhancer.setClassLoader(classLoader);
				if (classLoader instanceof SmartClassLoader &&
						((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
					enhancer.setUseCache(false);
				}
			}
      //设置代理接口、回调方法
			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);
		}
	}

通过使用AopProxy对象封装target目标对象之后,ProxyFactoryBeangetObject方法得到的对象就不是一个普通的Java对象了,而是一个AopProxy代理对象。在ProxyFactoryBean中配置的target目标对象,这时已经不会让应用直接调用其方法实现,而是作为AOP实现的一部分。对target目标对象的方法调用会首先被AopProxy代理对象拦截,对于不同的AopProxy代理对象生成方式,会使用不同的拦截回调人口。例如,对于JDK的AopProxy代理对象,使用的是InvocationHandler的invoke回调入口,而对于CGLIB的AopProxy代理对象,使用的是设置好的callback回调,这是由对CGLIB的使用来决定的。在这些callback回调中,对于AOP实现,是通过DynamicAdvisedInterceptor来完成的,而DynamicAdvisedInterceptor的回调入口是intercept方法。

至此,AOP代理对象已经生成,接下来分析AOP如何进行拦截。

拦截器实现

JDK代理拦截

在生成代理对象过程中,传入了this InvocationHandler对象,InvocationHandler是反射类接口,其中的invoke方法是作为JDK Proxy代理对象进行拦截的回调入口出现的,在JdkDynamicAopProxy中实现了InvocationHandler接口,也就是说当Proxy对象的代理方法被调用时,JdkDynamicAopProxy的invoke方法作为Proxy对象的回调函数被触发,从而通过invoke的具体实现,来完成对目标对象方法调用的拦截或者说功能增强的工作。

	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
		}
		return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
	}


	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 {
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				// The target does not implement the equals(Object) method itself.
        //如果目标对象没有实现Object类的基本方法:equals
				return equals(args[0]);
			}
			else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
				// The target does not implement the hashCode() method itself.
        // 如果目标对面没有实现Object类的hashCode方法
				return hashCode();
			}
			else if (method.getDeclaringClass() == DecoratingProxy.class) {
				// There is only getDecoratedClass() declared -> dispatch to proxy config.
				return AopProxyUtils.ultimateTargetClass(this.advised);
			}
			else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
					method.getDeclaringClass().isAssignableFrom(Advised.class)) {
				// Service invocations on ProxyConfig with the proxy config...
        // 根据代理对象的配置来调用服务
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			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.
			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.
        //如果没有设定拦截器,直接调用target的对应方法
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				// We need to create a method invocation...
        //如果有拦截器的设定,那么需要拦截器之后才调用目标对象的相应方法,通过ReflectiveMethodInvocation方法实现
				MethodInvocation invocation =
						new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				// Proceed to the joinpoint through the interceptor chain.
				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);


	@Override
	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.
		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) {
				// Add it conditionally.
				PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
				if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
					MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
					boolean match;
					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) {
             //拦截器链是通过AdvisorAdapterRegistry.来加入的,这个AdvisorAdapterRegistry
             //对advice织入起了很大的作用,在后面的分析中会看到
						MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
						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;
	}


在AdvisorAdapterRegistry中,提供了一系列的adapter适配器,正是这些adapter适配器的实现,为Spring AOP的advice:提供编织能力。

public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {

    private final List<AdvisorAdapter> adapters = new ArrayList<>(3);


    /**
     * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
     */
    public DefaultAdvisorAdapterRegistry() {
       registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
       registerAdvisorAdapter(new AfterReturningAdviceAdapter());
       registerAdvisorAdapter(new ThrowsAdviceAdapter());
    }


    @Override
    public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
       if (adviceObject instanceof Advisor) {
          return (Advisor) adviceObject;
       }
       if (!(adviceObject instanceof Advice)) {
          throw new UnknownAdviceTypeException(adviceObject);
       }
       Advice advice = (Advice) adviceObject;
       if (advice instanceof MethodInterceptor) {
          // So well-known it doesn't even need an adapter.
          return new DefaultPointcutAdvisor(advice);
       }
       for (AdvisorAdapter adapter : this.adapters) {
          // Check that it is supported.
          if (adapter.supportsAdvice(advice)) {
             return new DefaultPointcutAdvisor(advice);
          }
       }
       throw new UnknownAdviceTypeException(advice);
    }

    @Override
    public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
       List<MethodInterceptor> interceptors = new ArrayList<>(3);
       //从Advisor通知配置器中获取advice通知
       Advice advice = advisor.getAdvice();
      //如果通知是MethodInterceptor类型的通知,直接加入interceptors的list中
       if (advice instanceof MethodInterceptor) {
          interceptors.add((MethodInterceptor) advice);
       }
       //对通知进行适配,使用已经配置好的Adapter:MethodBeforeAdviceAdapter、
       //AfterReturningAdviceAdapterThrowsAdviceAdapter.
       //然后从对应的adapter中取出封装好AOP编织功能的拦截器
       for (AdvisorAdapter adapter : this.adapters) {
          if (adapter.supportsAdvice(advice)) {
             interceptors.add(adapter.getInterceptor(advisor));
          }
       }
       if (interceptors.isEmpty()) {
          throw new UnknownAdviceTypeException(advisor.getAdvice());
       }
       return interceptors.toArray(new MethodInterceptor[0]);
    }

    @Override
    public void registerAdvisorAdapter(AdvisorAdapter adapter) {
       this.adapters.add(adapter);
    }

}

查看适配器类结构:

image-20231016141603985

Spring AOP为了实现advice的织入,设计了特定的拦截器对这些功能进行了封装。虽然应用不会直接用到这些拦截器,但却是advice发挥作用必不可少的准
备。接着这条线索,还是以MethodBeforeAdviceInterceptor为例,看看它是怎样完成advice的封装的,MethodBeforeAdviceInterceptor完成的是对MethodBeforeAdvice通知的封装,可以在MethodBeforeAdviceInterceptor设计的invoke回调方法中,看到首先触发了advicebefore回调,然后才是MethodInvocationproceed方法调用。看到这里,就已经和前面在ReflectiveMethodInvocationproceed分析中联系起来了。回忆一下,在AopProxy代理对象触发的ReflectiveMethodInvocationproceed方法中,在取得拦截器以后,启动了对拦截器invoke方法的调用。按照AOP的配置规则,ReflectiveMethodInvocation触发的拦截器invoke方法,最终会根据不同的advice类型,触发Spring对不同的advicel的拦截器封装,比如对MethodBeforeAdvice,最终会触发MethodBeforeAdviceInterceptor的invoke方法。在MethodBeforeAdviceInterceptor方法中,会先调用advice的before方法,这就是
MethodBeforeAdvice所需要的对目标对象的增强效果:在方法调用之前完成通知增强。

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {

	private final MethodBeforeAdvice advice;


	/**
	 * Create a new MethodBeforeAdviceInterceptor for the given advice.
	 * @param advice the MethodBeforeAdvice to wrap
	 */
	public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
		Assert.notNull(advice, "Advice must not be null");
		this.advice = advice;
	}


	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
		return mi.proceed();
	}

}

CGLIB代理拦截

在CglibAopProxy类中,可以看到具体对CGLIB的使用,比如对Enhancer对象的配置,以及通过Enhancer对象生成代理对象的过程。在这个生成代理对象的过程中,需要注意的是对Enhancer对象callback回调的设置,正是这些回调封装了Spring AOP的实现,就像前面介绍的JDK的Proxy对象的invoke回调方法一样。在Enhancer的callback回调设置中,实际上是通过设置DynamicAdvisedInterceptor拦截器来完成AOP功能的,可以在getCallbacks方法实现中看到回调DynamicAdvisedInterceptor的设置,代码按下:

	private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
    ........
		@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();
				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...
					retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
				}
...

JDK代理和CGLIB主要是代理方式及AOP拦截的入口逻辑不一样,JDK代理是通过InvocationHandler回调实现AOP功能,CGLIB是通过设置DynamicAdvisedInterceptor拦截器来完成AOP功能。