Spring AOP的设计与实现——JDK动态代理、CGLIB动态代理

概念了解:

Spring AOP面向切面编程、动态代理的理解

深入理解SpringAOP中的动态代理


JVM的动态代理特性

在Spring AOP实现中,使用的核心技术是动态代理,这种动态代理实际上是JDK的一个特性。通过JDK的动态代理特性,可以为任意Java对象创建代理对象,通过Java Reflection API来完成。

在代理模式的的设计中,会设计一个接口和目标对象一致的对象Proxy,它们都实现了同一个接口的方法。对目标对象方法的调用,往往就被代理对象给拦截了,通过这种拦截,为目标对象方法操作做了铺垫,称为代理模式

在这里插入图片描述

配置ProxyFactoryBean

以ProxyFactoryBean的实现为例,一起来了解springAOP的具体设计和实现。ProxyFactoryBean可以在IOC容器中完成声明式配置,而使用ProxyFactory则需要编程式地使用spring AOP功能。

ProxyFactoryBean是在springIoC环境中创建AOP应用的底层方法,spring通过它完成了对AOP使用的封装。

ProxyFactoryBean的配置和使用

  • 定义使用的通知器Advisor,这个通知器应该作为一个Bean来定义,这个通知器的实现定义了需要对目标对象进行增强的切面行为,也就是Advice通知。
  • 在配置ProxyFactoryBean时,需要设定与AOP实现相关的重要属性,如ProxyInterface、InterceptorNames和target等。
  • 定义target属性,作为target属性注入的Bean,是需要用AOP通知器的切面应用来增强的对象。
<bean id="testAdvisor" class="com.example.spring.TestAdvisor"/>
	<bean id="testAOP" class="org.springframework.aop.framework.ProxyFactoryBean">
		<property name="proxyInterfaces">
			<value>
				com.example.AbcInterface
			</value>
		</property>
		<property name="interceptorNames">
			<list>
				<value>testAdvisor</value>
			</list>
		</property>
	</bean>

ProxyFactoryBean生成AOpProxy代理对象

ProxyFactoryBean是一个FactoryBean,在ProxyFactoryBean中,通过interceptorNames属性来配置已经定义好的通知器Advisor,供AOP应用配置通知器的地方。

ProxyFactoryBean需要为target目标对象生成Proxy代理对象,从而为AOP横切面的编织做好准备工作。这些具体的代理对象生成工作,是通过JDK的Proxy或CGLIB来完成的

ProxyFactoryBean的AOP实现需要依赖JDK或CGLIB提供的Proxy特性。从FactoryBean中获取对象,是以getObject方法作为入口完成的。

ProxyFactoryBean实现中的getObject方法是FactoryBean需要实现的接口,对ProxyFactoryBean来说,把需要对target目标对象增加的增强处理,都通过getObject方法进行封装了,这些增强视为AOP功能的实现提供服务的。

getObject方法首先对通知器链进行初始化,通知器链封装了一系列的拦截器,这些拦截器都要从配置中读取,然后为代理对象的生成做好准备,再生成代理对象时,因为spring对Bean由singleton和prototype之分,座椅要对代理对象的生成做一个区分。

在这里插入图片描述

	/**
	 * 返回代理。当客户从该FactoryBean获得bean时调用。 创建要由该工厂返回的AOP代理的实例。
	 */
	@Override
	@Nullable
	public Object getObject() throws BeansException {
		// 初始化通知器链
		initializeAdvisorChain();
		// 对singletion和prototype类型进行区分,生成对应的proxy
		if (isSingleton()) {
			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();
		}
	}
初始化通知器链

为Proxy代理对象配置Advisor链是在initializeAdvisorChain方法中完成的。

这个初始化过程有一个标志位AdvisorChainInitialized,用来表示通知器链是否已经初始化,也就是说这个初始化的工作发生在应用第一次通过ProxyFactoryBean去获取代理对象的时候。

在完成这个初始化之后,接着会读取配置中出现的所有通知器,这个过程把通知器的名字交给容器的getBean方法就可以了,通过对IoC容器的一个回调来完成,然后把IoC容器中去的的通知器介入拦截器链中,这个动作由addAdvisorOnChainCreation方法来实现。

private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
		// 通知器链是否已经初始化
		if (this.advisorChainInitialized) {
			return;
		}

		if (!ObjectUtils.isEmpty(this.interceptorNames)) {
			if (this.beanFactory == null) {
				throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
						"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
			}

			if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
					this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
				throw new AopConfigException("Target required after globals");
			}

			// 添加Advisor链的调用,通过interceptorNames属性进行配置的
			for (String name : this.interceptorNames) {
				if (name.endsWith(GLOBAL_SUFFIX)) {
					if (!(this.beanFactory instanceof ListableBeanFactory)) {
						throw new AopConfigException(
								"Can only use global advisors or interceptors with a ListableBeanFactory");
					}
					addGlobalAdvisors((ListableBeanFactory) this.beanFactory,
							name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
				}

				else {
					// 如果程序在这里被调用,那么需要加入命名的拦截器advice
					// ,并且需要检查这个Bean是singleton耗时prototype
					Object advice;

					// 如果是单例Bean 则将真正的Advisor / Advice添加到链中
					if (this.singleton || this.beanFactory.isSingleton(name)) {
						// Add the real Advisor/Advice to the chain.
						advice = this.beanFactory.getBean(name);
					}
					else {
					
						// 如果是prototype 用原型Bean Advisor代替
						advice = new PrototypePlaceholderAdvisor(name);
					}
					// 添加到链中
					addAdvisorOnChainCreation(advice);
				}
			}
		}

		this.advisorChainInitialized = true;
	}
生成单例Bean代理对象

生成singleton的代理对象在getSingletonInstance()中完成,这个方法是ProxyFactoryBean生成AopProxy代理对象的调用入口,代理对象会封装对target目标对象的调用,也就是说针对target对象的方法调用行为会被这里生成的代理对象所连接。

	/**
	 * 返回代理对象,如果没有创建则延迟创建
	 */
	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));
			}
			// Initialize the shared singleton instance.
			// 使用ProxyFactoryBean来生成需要的Proxy
			super.setFrozen(this.freezeProxy);
			this.singletonInstance = getProxy(createAopProxy());
		}
		return this.singletonInstance;
	}

这里出现了AopProxy类型的对象,spring利用这个AopProxy接口类把AOP代理对象的实现与框架的其他部分有效地分离开来,它有两个实现类,一个是Cglib2AopProxy另一个是JdkDynamicProxy,对这两个AopProxy接口的子类的实现,spring分别通过CGLIB和JDK来生成需要的Proxy代理对象。

ProxyCreatorSupport生成AopProxy对象

具体的代理对象生成,是在ProxyFactoryBean的基类AdvisorSupport的实现中借助AopProxyFactory完成的。至于生成什么样的代理对对象,所有信息都封装在AdvisorSupport里,这个对象也是生成AopProxy的方法的输入参数。

	protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		// 通过AopProxyFactory取得AopProxy,AopProxyFactory是在初始化函数中定义的,
		// 使用的是DefaultAopProxyFactory
		return getAopProxyFactory().createAopProxy(this);
	}

这里使用了AopProxyFactory来创建AopProxy,AopProxyFactory使用的是DefaultAopProxyFactory,这个被使用的AopProxyFactory作为AopProxy的创建工厂对象,在ProxyFactoryBean的基类ProxyCreatorSupport中被创建,在创建AopProxyFactory时,它被设置为DefaultAopProxyFactoryBean,问题就转换为在DefaultAopProxyFactory中,AopProxy是怎样生成的了。

在DefaultAopProxyFactory中创建AopProxy

对于AopProxy代理对象的生成,需要考虑使用哪种生成方式,如果目标对象是接口类,那么适合使用JDK来生成代理对象,否则spring会使用CGLIB来生成目标对象的代理对象。

DefaultAopProxyFactory创建AopProxy的过程是一个比较高层次的AopProxy代理对象的生成过程,对不同的AopProxy代理对象的生成所涉及的生成策略和场景做相应设计,但是对于具体的AopProxy代理对象的生成,最终并没有由DefaultAopProxyFactory来完成,而是由spring封装的jdkDynamicAopProxyCglibProxyFactory;类来完成的。

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (!IN_NATIVE_IMAGE &&
				(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
			// 从AdvisedSupport对象中取得配置的目标对象 
			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.");
			}
			// 如果tatgetClass是接口类,使用JDK来生成Proxy
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			// 如果不是接口类 使用CGLIB来生成Proxy
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

目标对象可以看做是,而AOP完成的是切面增强就是依附在这块皮上的

JDK生成AopProxy代理对象

ProxyFactoryBean在AopProxy代理对象和IoC容器配置之间起到了桥梁的作用,体现在它为代理对象的最终生成做好了准备。

在JDKDynamicAopProxy中,使用了JDK的Proxy类来生成代理对象,在生成Proxy对象之前,首先需要从Advised对象中取得代理对象的代理借口配置,然后调用Proxy的newProxyInstance方法,最终得到对应的Proxy代理对象。

在生成代理对象时,需要指明三个参数,一个类装载器,一个代理接口,另外一个就是Proxy回调方法所在的对象,这个对象需要实现InvocationHandler接口,这个InvocationHandler接口定义了invoke方法,提供代理对象的回调入口。

对于JdkDynamicAopProxy,它本身实现了InvocationHandler接口和invoke方法,这个invoke方法是Proxy代理对象的回调方法,所以可以使用this来把JDKDynamicAopProxy指派给Proxy对象,也就是说JDKDynamicAopProxy对象本身,在Proxy代理的几口方法被调用时,会触发invoke方法的回调,这个回调方法完成了AOP编织实现的封装。

	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);
	}
CGLIB生成AopProxy代理对象
public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
		}

		try {
			// 从advised中取得在IOC容器中配置的target对象
			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对象,包括设置代理接口,回调方法
			// 来自advised的IoC配置 比如使用AOP的DynamicAdvisedInterceptor拦截器
			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.
			// 通过Enhancer生成代理对象
			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);
		}
	}

通过对Enhancer对象生成代理对象的过程,在这个生成代理对象的过程中,需要注意的是对Enhancer对象callback回调的设置,正是这些回调封装了Spring AOP的实现,就像JDK的Proxy对象的invoke回调方法一样。在Enhancer的callback回调设置中,实际上是通过DynamicAdvisedInterceptor拦截器来完成AOP功能的。

对target目标对象的方法调用会首先被AopProxy代理对象拦截,对于不同AopProxy代理对象生成方式,会使用不同的拦截回调入口。对于JDK的AopProxy代理对象,使用InvocationHandler的invoke回调入口,而对于CGLIB的AopProxy代理对象,使用的是设置好的callback回调,这是由对CFLIB的使用来决定的。

Spring AOP拦截器调用的实现

设计原理

在spring AOP通过JDK的Proxy方法或者CGLIB方式生成代理对象的时候,相关拦截器已经配置到代理对象中去了,拦截器在代理对象中起作用是通过这些方法的回调来完成的。

如果使用JDK的Proxy来生成代理对象,那么需要通过InvocationHandler来设置拦截器回调,而如果使用CGLIB来生成代理像,就需要根据CGLIB的使用要求,通过DynamicAdviseInterCeptor来完成回调。

JDKDynamicAopProxy的invoke拦截

在JDKDynamicAopProxy中生成Proxy对象时,它的AopProxy代理对象的生成调用:

Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);

这里的this参数对应的是InvocationHandler对象,InvocationHandler是JDK定义的反射类的一个接口,这个接口定义了invoke方法,而这个invoke方法是作为JDK Proxy代理对象进行拦截的回调入口实现的。

当Proxy对象的代理方法被调用时,JDKDynamicAopProxy的invoke方法作为Proxy对象的回调函数被触发。

对Proxy对象的代理设置是在invoke方法中完成的,这些设置包括获取目标对象、拦截器链,同时把这些对象作为输入,创建ReflectiveMethodInvocation对象,通过这个对象来完成AOP功能实现的封装。在这个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 {
			// 如果目标对象没有实现Object类的equals方法
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				// The target does not implement the equals(Object) method itself.
				return equals(args[0]);
			}
			// 如果目标对象没有实现Object类的hashcode方法
			else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
				// The target does not implement the hashCode() method itself.
				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;

			if (this.advised.exposeProxy) {
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}
			// 得到目标对象
			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);

			// 获得定义改的拦截器链
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

			// 如果没有设定拦截器 则直接调用target的对应方法
			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);
				// 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())) {
				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);
			}
		}
	}
Cglib的Intercept拦截
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

		private final AdvisedSupport advised;

		public DynamicAdvisedInterceptor(AdvisedSupport advised) {
			this.advised = advised;
		}

		@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) {
					oldProxy = AopContext.setCurrentProxy(proxy);
					setProxyContext = true;
				}
				// 从advised中取得配置好的AOP通知
				target = targetSource.getTarget();
				Class<?> targetClass = (target != null ? target.getClass() : null);
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
				Object retVal;

				// 如果没有AOP通知配置,那么直接调用target对象的调用方法
				if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
					Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
					retVal = methodProxy.invoke(target, argsToUse);
				}
				else {
					// 通过CglibMethodInvocation来启动advice通知
					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);
				}
			}
		}
目标对象方法的调用

如果没有设置拦截器,那么会对目标对象的方法直接进行调用,对于JDKDynamicAopProxy代理对象,这个目标对象的方法调用是通过AopUtils使用反射机制在AopUtils.invokeJoinpointUsingReflection中实现的。

	public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
			throws Throwable {

		// Use reflection to invoke the method.
		// 使用反射调用target对象方法的地方
		try {
			ReflectionUtils.makeAccessible(method);
			return method.invoke(target, args);
		}
		catch (InvocationTargetException ex) {
			// Invoked method threw a checked exception.
			// We must rethrow it. The client won't see the interceptor.
			// 抛出AOP异常,对异常进行类型转换
			throw ex.getTargetException();
		}
		catch (IllegalArgumentException ex) {
			throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
					method + "] on target [" + target + "]", ex);
		}
		catch (IllegalAccessException ex) {
			throw new AopInvocationException("Could not access method [" + method + "]", ex);
		}
	}

CGLIB代理对目标对象的调用是通过CGLIB的MethodProxy对象来直接完成的,这个对象的使用是由CGLIB的设计决定的。具体的调用在DynamicAdvisedInterceptor的Intercept方法中可以看到。retVal = methodProxy.invoke(target, argsToUse);

AOP拦截器链的调用

AOP是怎样完成对目标对象的增强的,这些实现封装在AOP拦截器链中,由一个个具体的拦截器来完成。

虽然jdk代理和cglib代理使用了不同的AopProxy代理对象,但最终对AOP拦截的处理殊途同归,它们对拦截器链的调用都是在ReflectiveMethodInvocation中通过proceed方法实现的。在proceed方法中,会逐个运行拦截器的拦截方法,在运行拦截器的拦截方法之前,需要对代理方法完成一个匹配判断,通过这个匹配判断来决定拦截器是否满足切面增强的要求。

在proceed方法中,先进性判断,如果现在已经运行到拦截器末尾,那么就会直接调用目标对象的实现方法,否则,沿这拦截器链继续进行,得到下一个拦截器,通过这个拦截器进行matches判断,判断是否适用于横切增强的场合。如果是,从拦截器中得到通知器,并启动通知器的invoke方法进行切面增强。这个过程结束以后,会迭代调用proceed方法,直到拦截器链中的拦截器都完成以上的拦截过程为止。

@Override
	@Nullable
	public Object proceed() throws Throwable {
		// We start with an index of -1 and increment early.
		// 从索引为-1的拦截器开始调用,并按序递增,如果拦截器链中的拦截器迭代调用完毕,这里开始调用target的函数
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			return invokeJoinpoint();
		}

		// 沿这定义好的interceptorOrInterceptionAdvice 链进行处理
		Object interceptorOrInterceptionAdvice =
				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
		if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
			// Evaluate dynamic method matcher here: static part will already have
			// been evaluated and found to match.
			// 对拦截器进行动态匹配判断,触发进行匹配的地方,如果和定义的Pointcut匹配,
			// 那么这个advice会得到执行
			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 {
				// Dynamic matching failed.
				// Skip this interceptor and invoke the next in the chain.
				// 如果不匹配,那么proceed会被递归调用,直到所有拦截器都被运行过为止
				return proceed();
			}
		}
		else {
			// It's an interceptor, so we just invoke it: The pointcut will have
			// been evaluated statically before this object was constructed.
			// 如果是一个Interceptor 直接调用这个Interceptor对应的方法
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}

配置通知器

AdvisedSupport取得拦截器

利用cache去获取已有的Interceptor链,但是第一次需要自己动手生成,这个Interceptor链的生成是由AdvisorChainFactory完成的,这里使用的是DefaultAdvisorChainFactory。

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

	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;
	}
DefaultAdvisorChainFactory生成拦截器链

从名字可以看到该工厂是一个生成通知链的工厂,它实现了Interceptor链的获取过程。

这个过程中,首先设置一个List,其长度是由配置的通知器的个数来决定的,这个配置就是XML中对ProxyFactoryBean做的interceptNames属性的配置。然后DefaultAdvisorChainFactory会通过一个AdvisorAdapterRegistry来实现拦截器的注册,有了AdvisorAdapterRegistry的注册器,利用它来对ProxyFactoryBean配置中得到的通知进行适配,从而获得相应的拦截器,再把它加入前面设置好的List中,完成拦截器注册过程。

在拦截器适配和注册过程完成后,List中的拦截器会被JDK生成的AopProxy代理对象的invoke方法或者CGLIB代理对象的interceptor拦截方法取得,并启动拦截器的invoke调用,最终触发通知的切面增强。

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链已经在config中持有了,直接使用
		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) {
			// 由切入点驱动的所有Advisor的接口。 这几乎涵盖了除介绍拦截器之外的所有拦截器,不适用于方法级匹配
			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) {
						// 获取到达目标的接口上的拦截调用
						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));
						}
					}
				}
			}
			// 执行一个或多个AOP拦截器的接口
			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;
	}

	/**
	 * 判断Advisors是否符合配置要求
	 * Determine whether the Advisors contain matching introductions.
	 */
	private static boolean hasMatchingIntroductions(Advisor[] advisors, Class<?> actualClass) {
		for (Advisor advisor : advisors) {
			if (advisor instanceof IntroductionAdvisor) {
				IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
				if (ia.getClassFilter().matches(actualClass)) {
					return true;
				}
			}
		}
		return false;
	}

在拦截器链的初始化中获取Advisor通知器

在ProxyFactoryBean的getObject方法中对Advisor进行初始化时,从XML配置中获取了Advisor通知器。

Advisor通知器的取得是委托给IoC容器完成的,但是在ProxyFactoryBean中是如何获得IoC容器,然后通过回调IoC容器的getBean方法来得到需要的通知器的呢?

在使用DefaultListableBeanFactory作为IoC容器的时候,它的基类是AbstractAutowireCapableBeanFactory,在这个积累中有一个对Bean进行初始化的initializeBean方法,在这个Bean的初始化过程中,对IoC容器在Bean中的回调进行设置。

首先判断这个Bean的类型是不是实现了BeanFactoryAware接口,如果是,则通过实现的接口方法,把IoC容器设置到Bean自身定义的一个属性中去。这样在这个Bean的自身实现中就能够得到它所在的IoC容器,从而掉用IoC容器的getBean方法,完成对IoC容器的回调。除了使用为自己设计的功能外,还可以调用它所在的容器的功能。

			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}

对于IoC容器的使用,如果需要回调容器,前提是当前Bean需要实现BeanFactoryAware接口,这个接口只需要实现setBeanFactory方法同时设置一个属性来只有BeanFactory的IoC容器,就可以在Bean中取得IoC容器进行回调了,在IoC容器对Bean进行初始的时候,对Bean进行判断,如果是BeanFactoryAware类型,则会将IoC设置到这个Bean中,设置好以后,ProxyFactoryBean就可以通过回调同期的getBean去获取配置在Bean定义文件中的通知器了,获取通知器就是向IoC容器回调getBean的过程。

ProxyFactoryBean需要给出通知器的名字,而这些名字都是在InterceptorNames的List中配置好的,在IoC对FactoryBean进行依赖注入的时候,会直接注入到FactoryBean的InterceptorNames属性中,完成这个过程后,ProxyFactoryBean就获得了配置的通知器,为完成切面增强做好准备。

Advice通知的实现

前面了解到,在生成拦截器链的过程中,有一个适配和注册的过程,通过配置spring预计设计好的拦截器,spring加入了它对AOP实现的处理。为了详细了解这个过程,先从DefaultAdvisorChainFactory的实现开始,首先构造了一个GlobalAdvisorAdapterRegistry单例对象,然后对配置的Advisor通知器进行逐个辨别能力,这个通知器链都是配置在InterceptorNames中的,从getInterceptorsAndDynamicInterceptionAdvice传进来的advised参数对象汇总可以方便获取配置的通知器,有了这些通知器,接着就是一个由GlobalAdvisorAdapterRegistry来完成的拦截器的适配和注册过程。

		// 得到注册器 单例模式实现的
		AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

它的实例是一个DefaultAdvisorAdapterRegistry

public final class GlobalAdvisorAdapterRegistry {

	private GlobalAdvisorAdapterRegistry() {
	}

	private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry();
	
	}

DefaultAdvisorAdapterRegistry中,设置了一系列adapter适配器,正是这些adapter适配器的实现,为spring AOP的advice提供编织能力。

这些adapter的使用主要体现在以下两个方面:

  1. 调用adapter的support方法,通过这个方法来判断取得的advice属于什么类型的advice通知,从而根据不同的advice类型类注册不同的AdviceInterceptor,也就是前面的拦截器。
  2. 这些AdviceInterceptor都是Spring AOP框架设计好了的,是为实现不同的advice功能提供服务的,有了这些AdviceInterceptor,可以方便地使用spring提供的各种不同的advice来设计AOP应用。
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {

	/**
	 * 持有一个AdvisorAdapter的List 这个List中的Adapter是与实现spring AOP的advice增强功能相对应的
	 */
	private final List<AdvisorAdapter> adapters = new ArrayList<>(3);


	/** 把已有的advice实现的Adapter加入进来
	 * 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,然后从对应的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);
	}

}

DefaultAdvisorAdapterRegistry的getInterceptors调用中,从MethodBeforeAdviceAdapterAfterReturningAdviceAdapterThrowsAdviceAdapter这几个通知适配器的名字可以看到,他们和advice意义对应,这里作为适配器被加入到adapter的List中,从这及各类的设计层次和关系看,它们都是实现AdvisorAdapter接口的同一层次类,只是承担着不同的适配任务,一对一服务于不同advice实现。

在这里插入图片描述

MethodBeforeAdviceAdapter为例,它实现了AdvisorAdapter的两个接口方法,一个是supportsAdvice,对advice类型进行判断,另一个是对getInterceptor接口方法的实现,这个方法把advice通知从通知器中取出,然后创建一个MethodBeforeAdviceInterceptor对象,通过这个对象把取得的advice通知包装起来。

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

	@Override
	public boolean supportsAdvice(Advice advice) {
		return (advice instanceof MethodBeforeAdvice);
	}

	@Override
	public MethodInterceptor getInterceptor(Advisor advisor) {
		MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
		return new MethodBeforeAdviceInterceptor(advice);
	}
}
MethodBeforeAdviceInterceptor的实现

springAOP为了实现advice的织入设计了特定的拦截器对这些功能进行了封装,以MethodBeforeAdviceInterceptor为例,它是如何完成advice的封装的。

在invoke回调方法中,首先触发了advice的before回调,然后才是MethodInvocation的proceed方法调用。

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {

	private final MethodBeforeAdvice advice;


	/**
	 * 为指定的Advice创建对应的MethodBeforeAdviceInterceptor
	 */
	public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
		Assert.notNull(advice, "Advice must not be null");
		this.advice = advice;
	}


	@Override
	@Nullable
	/**
	 * 这个invoke方法是拦截器的回调方法,会在代理对象的方法被调用时触发回调
	 */
	public Object invoke(MethodInvocation mi) throws Throwable {
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
		return mi.proceed();
	}

}
AfterReturnAdviceInterceptor的实现

对于其他的advice通知也可以举一反三,如AfterReturnAdviceInterceptor的实现,先完成MethodInvocation的proceed调用,也就是目标对象的方法调用,然后再启动advice通知afterReturning回调。

public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {

	private final AfterReturningAdvice advice;

	public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
		Assert.notNull(advice, "Advice must not be null");
		this.advice = advice;
	}


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

}

ThrowsAdviceInterceptor的实现

相比于其余两个拦截器,它维护了一个exceptionHandlerMap来对应不同的方法调用场景。

public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice {

	private static final String AFTER_THROWING = "afterThrowing";

	private static final Log logger = LogFactory.getLog(ThrowsAdviceInterceptor.class);


	private final Object throwsAdvice;

	/** Methods on throws advice, keyed by exception class. */
	private final Map<Class<?>, Method> exceptionHandlerMap = new HashMap<>();

	public ThrowsAdviceInterceptor(Object throwsAdvice) {
		Assert.notNull(throwsAdvice, "Advice must not be null");
		this.throwsAdvice = throwsAdvice;

		// 配置ThrowsAdvice的回调方法
		Method[] methods = throwsAdvice.getClass().getMethods();
		for (Method method : methods) {
			if (method.getName().equals(AFTER_THROWING) &&
					(method.getParameterCount() == 1 || method.getParameterCount() == 4)) {
				Class<?> throwableParam = method.getParameterTypes()[method.getParameterCount() - 1];
				if (Throwable.class.isAssignableFrom(throwableParam)) {
					// An exception handler to register...
					this.exceptionHandlerMap.put(throwableParam, method);
					if (logger.isDebugEnabled()) {
						logger.debug("Found exception handler method on throws advice: " + method);
					}
				}
			}
		}
		// 配置异常处理
		if (this.exceptionHandlerMap.isEmpty()) {
			throw new IllegalArgumentException(
					"At least one handler method must be found in class [" + throwsAdvice.getClass() + "]");
		}
	}

	public int getHandlerMethodCount() {
		return this.exceptionHandlerMap.size();
	}


	@Override
	@Nullable
	public Object invoke(MethodInvocation mi) throws Throwable {
		try {
			// 把对目标对象的方法调用放入try/catch 中,并在catch中触发ThrowsAdvice的回调
			// 把异常接着向外抛出,不做过多处理
			return mi.proceed();
		}
		catch (Throwable ex) {
			Method handlerMethod = getExceptionHandler(ex);
			if (handlerMethod != null) {
				invokeHandlerMethod(mi, ex, handlerMethod);
			}
			throw ex;
		}
	}

	@Nullable
	private Method getExceptionHandler(Throwable exception) {
		Class<?> exceptionClass = exception.getClass();
		if (logger.isTraceEnabled()) {
			logger.trace("Trying to find handler for exception of type [" + exceptionClass.getName() + "]");
		}
		Method handler = this.exceptionHandlerMap.get(exceptionClass);
		while (handler == null && exceptionClass != Throwable.class) {
			exceptionClass = exceptionClass.getSuperclass();
			handler = this.exceptionHandlerMap.get(exceptionClass);
		}
		if (handler != null && logger.isTraceEnabled()) {
			logger.trace("Found handler for exception of type [" + exceptionClass.getName() + "]: " + handler);
		}
		return handler;
	}

	// 通过反射启动对ThrowsAdvice回调方法的调用
	private void invokeHandlerMethod(MethodInvocation mi, Throwable ex, Method method) throws Throwable {
		Object[] handlerArgs;
		if (method.getParameterCount() == 1) {
			handlerArgs = new Object[] {ex};
		}
		else {
			handlerArgs = new Object[] {mi.getMethod(), mi.getArguments(), mi.getThis(), ex};
		}
		try {
			method.invoke(this.throwsAdvice, handlerArgs);
		}
		catch (InvocationTargetException targetEx) {
			throw targetEx.getTargetException();
		}
	}

}

ProxyFactory实现AOP

除了使用ProxyFactoryBean实现AOP应用之外,还可以使用ProxyFactory来实现Spring AOP功能,只是在使用ProxyFactory的时候,需要编程式完成AOP应用的设置。

在这里插入图片描述
与ProxyFactoryBean实现AOP相比,ProxyFactory没有使用FactoryBean的IoC封装,而是通过直接继承ProxyCreatorSupport的功能来完成AOP的属性配置。

同样获取代理对象的时候也是以getProxy为入口,由DefaultAopProxyFactory来完成的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值